为什么生产者-消费者代码不起作用?
Why Producer-Consumer code is not working?
我正在尝试在信号量的帮助下编写解决生产者-消费者问题的代码。
下面是我写的代码,执行时产生一个数字就卡住了。
我检查了两个信号量的分配,看起来没问题。
调用获取和释放方法的顺序看起来也是正确的。
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();
}
不要使用 2 个信号量,而只使用 1 个。n
的值最终将在 2 个线程之间共享,因此它是唯一需要同步的东西,因为信号量本质上是 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;
}
}
}
我正在尝试在信号量的帮助下编写解决生产者-消费者问题的代码。 下面是我写的代码,执行时产生一个数字就卡住了。
我检查了两个信号量的分配,看起来没问题。 调用获取和释放方法的顺序看起来也是正确的。
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();
}
不要使用 2 个信号量,而只使用 1 个。n
的值最终将在 2 个线程之间共享,因此它是唯一需要同步的东西,因为信号量本质上是 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;
}
}
}