繁体   English   中英

队列的同步

[英]Synchronization of a Queue

我一直在阅读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; }
  }
}

这是一个非常好的队列。 它使用两个监视器,因此Producer和Consumer可以同时访问Queue。 太好了! 但是,'last'和'head'的同步让我感到困惑。 该书指出,对于Queue当前或即将有0个条目的情况,这是必需的。 好吧,公平,这种做法很有道理。

但是,然后我查看了Java Concurrency LinkedBlockingQueue。 队列的原始版本不会在头部或尾部同步(我也想发布另一个链接到现代版本,它也遇到同样的问题,但我不能这样做因为我是新手)。 我想知道为什么不呢? 我在这里错过了什么吗? 是否缺少Java内存模型特殊性质的某些部分? 为了可见性,我会考虑需要这种同步吗? 我很欣赏一些专家意见!

这里的细微之处在于synchronized(null)会抛出NullPointerException,因此head和last都不允许变为null。 它们都被初始化为永远不会从任何列表返回或删除的同一虚拟节点的值。

put()和poll()在两个不同的锁上同步。 如果这些方法可以从不同的线程修改相同的值,那么这些方法需要在同一个锁上同步,以便相互之间是线程安全的。 这是一个问题的唯一情况是head == last(即它们是同一个对象,通过不同的成员变量引用)。 这就是代码在头部和最后同步的原因 - 大部分时间这些都是快速,无条件的锁定,但偶尔头部和最后一个将是同一个实例,其中一个线程将不得不阻塞另一个。

可见性问题的唯一时间是当队列几乎为空时,剩余的时间put()和poll()在队列的不同端工作,并且不会相互干扰。

在版本中,您为最新JRE中的版本以及最新JRE中的版本提供了一个链接,Node类中的项目是volatile,它强制读取和写入对所有其他线程可见,这里有更深入的解释http:// www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM