我一直在阅读Doug Lea的“Java中的并发编程”一书。您可能知道,Doug最初编写了Java Concurrency API。但是,有些事情使我感到困惑,我希望就这个小难题获得一些我的看法!同步队列
看看下面的代码Doug Lea的排队例子...
class LinkedQueue {
protected Node head = new Node(null);
protected Node last = head;
protected final Object pollLock = new Object();
protected final Object putLock = new Object();
public void put(Object x) {
Node node = new Node(x);
synchronized (putLock) { // insert at end of list
synchronized (last) {
last.next = node; // extend list
last = node;
}
}
}
public Object poll() { // returns null if empty
synchronized (pollLock) {
synchronized (head) {
Object x = null;
Node first = head.next; // get to first real node
if (first != null) {
x = first.object;
first.object = null; // forget old object
head = first; // first becomes new head
}
return x;
}
}
}
static class Node { // local node class for queue
Object object;
Node next = null;
Node(Object x) { object = x; }
}
}
这是一个相当不错的队列。它使用两台显示器,因此生产者和消费者可以同时访问队列。太好了!然而,'last'和'head'的同步让我很困惑。该书指出这是队列目前或将要有0个条目的情况所需要的。好吧,够公平的,这是有道理的。
不过,后来我看了一下Java Concurrency LinkedBlockingQueue。队列的original版本在头部或尾部不同步(我也想发布另一个链接到现代版本,它也遭受同样的问题,但我不能这样做,因为我是一个新手)。我想知道为什么不呢?我在这里错过了什么吗?是否存在我缺少的Java内存模型的某些特殊性质?我会想到可见性的目的,这种同步是必要的?我会感谢一些专家意见!
请注意,我目前的理论是关于'signalNotEmpty'方法进入'takeLock'的synchronized块。这也许会迫使“头”被看到。 – 2010-02-27 12:14:22