iteye_12127
iteye_12127
2011-03-21 18:24

多线程问题,大家来找错。。。

已采纳

今天看了一个有BUG的多线程代码,但是怎么看也没看出问题来,高手来解释解释吧.

代码:


import java.util.*;
public class PrintQueue {
private LinkedList<String> queue = new LinkedList<String>();
private final Object lock = new Object();
public void enqueue(String str) {
synchronized (lock) {
queue.addLast(str);
lock.notifyAll();
}
}
public void work() {
String current;
synchronized(lock) {
if (queue.isEmpty()) {
try {
lock.wait();
} catch (InterruptedException e) {
assert (false);
}
}
current = queue.removeFirst();
}
System.out.println(current);
}
public static void main(String[] args) {
final PrintQueue pq = new PrintQueue();
Thread producer1 = new Thread() {
public void run() {
pq.enqueue("anemone");
pq.enqueue("tulip");
pq.enqueue("cyclamen");
}
};
Thread producer2 = new Thread() {
public void run() {
pq.enqueue("iris");
pq.enqueue("narcissus");
pq.enqueue("daffodil");
}
};
Thread consumer1 = new Thread() {
public void run() {
pq.work();
pq.work();
pq.work();
pq.work();
}
};
Thread consumer2 = new Thread() {
public void run() {
pq.work();
pq.work();
}
};
producer1.start();
consumer1.start();
consumer2.start();
producer2.start();
}
}


问题补充
AllenZhang 写道
两个work工作,分别都进入了wait状态


这个是有同步锁的怎么可能两个都进呢?
synchronized(lock)
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • Allen2004 Allen2004 10年前

    。。。。。。。。
    wait会释放锁

    点赞 评论 复制链接分享
  • changchanghust changchanghust 10年前

    这个问题比较典型啦。因为你使用的是notifyAll,所有wait阻塞的线程都会被唤醒,所以会出现两个线程都去removeFirst,但队列里只有一个元素的情况。
    解决的办法就是wait应该放在循环体内,当线程被唤醒后,要再次检查条件是否成立才继续执行。把work方法里的
    [code="java"]if (queue.isEmpty()) { [/code]
    改成
    [code="java"]while (queue.isEmpty()) { [/code]
    就可以了。

    点赞 评论 复制链接分享
  • Allen2004 Allen2004 10年前

    当queue为空,两个work工作,分别都进入了wait状态。
    当queue中有放入一个元素的时候,因为notifyAll,所有work都被唤醒。
    唤醒后,会分别执行queue.removeFirst()一次,导致NoSuchElementException

    点赞 评论 复制链接分享

相关推荐