我一直在阅读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; }
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常好的队列.它使用两个监视器,因此Producer和Consumer可以同时访问Queue.太好了!但是,'last'和'head'上的同步让我感到困惑.该书指出,对于Queue当前或即将有0个条目的情况,这是必需的.好吧,公平,这种做法很有道理.
但是,然后我查看了Java Concurrency LinkedBlockingQueue.队列的原始版本不会在头部或尾部同步(我也想发布另一个链接到现代版本,它也遇到同样的问题,但我不能这样做因为我是新手).我想知道为什么不呢?我在这里错过了什么吗?是否缺少Java内存模型特殊性质的某些部分?为了可见性,我会考虑需要这种同步吗?我很欣赏一些专家意见!
在您提供链接的版本以及最新 JRE 中的版本中,Node 类内的项目是易失性的,它强制读取和写入对所有其他线程可见,这里有更深入的解释 http: // www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
| 归档时间: |
|
| 查看次数: |
2819 次 |
| 最近记录: |