java - 为什么生产者-消费者代码不起作用?
问题描述
我正在尝试在信号量的帮助下编写生产者-消费者问题的解决方案。下面是我编写的代码,在执行时它在生成一个数字后卡住了。
我已经检查了信号量的分配,它看起来很好。调用的获取和释放方法的顺序看起来也是正确的。
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();
}
}
解决方案
你已经做了get
和put
synchronized
。所以生产者进入,锁定q
,使用一个许可,producerSem
并在下一次put
调用时阻塞。不幸的是,q
仍然被生产者锁定,因此消费者将无法进入get
。要解决此问题,请删除两个synchronized
s。
现在要同步对 的访问n
,synchronized
仅使用访问的地方 n
,而不是整个方法。
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();
}
推荐阅读
- r - 使用 R/Plotly 更改热图的 y 轴刻度值
- php - 尝试使用 php 准备好的语句和 mysqli 执行更新/插入查询,但无济于事
- excel - cyber-duck/laravel-excel 文件损坏/格式无效
- python - Python 将 x,y 数据转换为纬度和经度数据
- java - 无法使用 Eclipse 导出产品
- jquery - 在ajax中引用锚标记
- impala - 无法使用 impala-shell 在 kudu 中创建表
- objective-c - 支持 macOS 10.14 Mojave 中的工具栏可见性
- database - 持久化docker容器的数据库
- c# - 如何使用 JavaScriptSerializer 序列化日期