英文:
Why Producer-Consumer code is not working?
问题
以下是您提供的代码的翻译部分:
我正在尝试使用信号量解决生产者-消费者问题。
以下是我编写的代码,在执行后,在生产一个数字后就停止运行。
我已经检查了信号量的分配,看起来是正确的。
调用的acquire和release方法的顺序也看起来是正确的。
public class Q {
int n;
Semaphore consumerSem = new Semaphore(0);
Semaphore producerSem = new Semaphore(1);
synchronized void get(){
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Got Data : " + n);
producerSem.release();
}
synchronized void put(int n){
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Putting Data : " + n);
this.n=n;
consumerSem.release();
}
}
public class Producer implements Runnable{
Q q;
Producer(Q q){
this.q = q;
}
@Override
public void run() {
for (int i=0; i<20;i++){
q.put(i);
}
}
}
public class Consumer implements Runnable{
Q q;
Consumer(Q q){
this.q = q;
}
@Override
public void run() {
for (int i =0;i<20;i++){
q.get();
}
}
}
public class PCRun {
public static void main(String[] args) {
Q q = new Q();
new Thread(new Producer(q),"Producer").start();
new Thread(new Consumer(q),"Consumer").start();
}
}
请注意,由于您要求只返回翻译后的内容,我已经删除了任何其他的回答或附加信息。如果您有关于这段代码的问题或需要进一步的帮助,请随时提问。
英文:
I am trying to code solution of Producer-Consumer problem with the help of Semaphores.
Below is the code I have written, on execution it is getting stuck after producing one number.
I have checked the assignment of both the Semaphore and it look fine.
The sequence of acquire and release methods being called also looks correct.
public class Q {
int n;
Semaphore consumerSem = new Semaphore(0);
Semaphore producerSem = new Semaphore(1);
synchronized void get(){
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Got Data : " + n);
producerSem.release();
}
synchronized void put(int n){
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Putting Data : " + n);
this.n=n;
consumerSem.release();
}
}
public class Producer implements Runnable{
Q q;
Producer(Q q){
this.q = q;
}
@Override
public void run() {
for (int i=0; i<20;i++){
q.put(i);
}
}
}
public class Consumer implements Runnable{
Q q;
Consumer(Q q){
this.q = q;
}
@Override
public void run() {
for (int i =0;i<20;i++){
q.get();
}
}
}
public class PCRun {
public static void main(String[] args) {
Q q = new Q();
new Thread(new Producer(q),"Producer").start();
new Thread(new Consumer(q),"Consumer").start();
}
}
答案1
得分: 1
你已经将get
和put
两个方法进行了同步。因此,生产者进入后会锁定q
,使用了producerSem
的一个许可,在下一次put
调用时会被阻塞。不幸的是,q
仍然被生产者锁定,因此消费者无法进入get
方法。为了修复这个问题,请移除两个Synchronized
关键字。
现在,为了同步对n
的访问,在访问n
的地方使用synchronized
关键字,而不是整个方法。
int n;
final Semaphore consumerSem = new Semaphore(0);
final Semaphore producerSem = new Semaphore(1);
void get() {
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println("获取数据:" + n);
}
producerSem.release();
}
void put(int n) {
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) { // 不变式:打印 + 写入,原子操作
System.out.println("放置数据:" + n);
this.n = n;
}
consumerSem.release();
}
英文:
You've made get
and put
synchronized
. So the producer goes in, locks q
, uses the one permit of producerSem
and blocks at the next put
call. Unfortunately, q
is still locked by the producer, so the consumer won't be able to enter get
. To fix this, remove both synchronized
s.
Now to synchronize the access on n
, use synchronized
only where n
is accessed, not for both whole methods.
int n;
final Semaphore consumerSem = new Semaphore(0);
final Semaphore producerSem = new Semaphore(1);
void get() {
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println("Got Data : " + n);
}
producerSem.release();
}
void put(int n) {
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) { // invariant print + write, atomic
System.out.println("Putting Data : " + n);
this.n = n;
}
consumerSem.release();
}
答案2
得分: 0
代替使用2个信号量,只使用1个。变量n
的值最终将在2个线程之间共享,因此它是唯一需要同步的内容,因为信号量在本质上是线程安全的。
public static class Q {
int n;
Semaphore available = new Semaphore(0);
void get() throws InterruptedException {
available.acquire();
synchronized (this) {
System.out.printf("获取 %s\n", n);
}
}
void put(int n){
available.release();
synchronized (this) {
System.out.printf("放置 %s\n", n);
this.n = n;
}
}
}
英文:
Instead of using 2 semaphores, only use 1. The value of n
will ultimately be shared among 2 threads so it's the only thing that needs to be synchronized because Semaphores are inherently thread-safe.
public static class Q {
int n;
Semaphore available = new Semaphore(0);
void get() throws InterruptedException {
available.acquire();
synchronized (this) {
System.out.printf("Get %s\n", n));
}
}
void put(int n){
available.release();
synchronized (this) {
System.out.printf("Put %s\n", n);
this.n = n;
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论