【问题标题】:What's the best alternative to wait...notify for low level synchronization?等待...通知低级同步的最佳选择是什么?
【发布时间】:2011-02-06 07:25:43
【问题描述】:

据我所知,wait()notify() 已经被更好的并发机制所取代。那么,你会选择什么更好的替代方案,比如实现a synchronized queue

它们究竟在什么意义上“更好”?

编辑:这个(“实现同步队列”)是一个面试问题。可接受的答案不能使用 BlockingQueue 或其他队列实现。但是,它可能会使用其他同步构造,例如 CountDownLatch。我没有详尽的允许和禁止课程列表 - 用你的头脑。

【问题讨论】:

  • 我不会实现同步队列。我会使用 BlockingQueue 的众多实现之一:download.oracle.com/javase/6/docs/api/java/util/concurrent/…
  • @Mike - 我正在准备面试。在现实生活中,我会使用现有的东西而不是重新发明。
  • 那我恐怕不明白这个问题。同步块和等待/通知已被 java.util.concurrent 包中的类形式的高级抽象取代,而不是新的语言结构。如果问题的目的是利用一些 java.util.concurrent 类,我们排除了哪些类?
  • @Mike - 我没有详尽的允许和禁止类列表,但很明显 BlockingQueue 在禁止列表中。

标签: java multithreading concurrency


【解决方案1】:

synchronized/wait()/notify()/notifyAll() 已直接被 Lock 类方法 lock()/unlock()/newCondition() 和 Condition 的 await()/signal()/signalAll() 替换。

这些有几个好处,首先允许诸如公平策略之类的附加语义,以及诸如分布式锁定之类的特性。对多个 Condition 对象的支持允许更细粒度的信令以及不间断的等待和等待一段时间等。

例如,链接代码具有尝试用于信号的单独对象(由于相关监视器在等待时未保持这一事实,这将失败)。这可以通过使用具有多个条件的单个 Lock 直接替换。

在改进方面,附加功能可能很有价值。在 Java5 中,显式 Lock 实现实际上比 JVM 监视器执行得更好,但它们基本上对 Doug Lea 的 JVM 代码进行了修改,现在性能大致相当。

【讨论】:

  • 我认为说语言原语已被“替换”并不准确。事实上,在 Java 8+ 中,某些用途(例如 ConcurrentHashMap)实际上已经切换回同步/等待/通知,因为性能比使用笨拙的 java.util.concurrent.locks 库更好(“尴尬”引用自 Javadocs 本身!)
【解决方案2】:

java.util.concurrent 包中已经存在很多实现。例如。 -ArrayBlockingQueueDelayQueueLinkedBlockingQueuePriorityBlockingQueueSynchronousQueue

wait()notify() 也没有被替换。引入了新的实用程序,可提供额外的功能和性能优势。例如,请参阅 java.util.concurrent.locks 包。

我建议您阅读this 简介。它提供了一个高度概述,应该可以回答您的问题。

干杯。

编辑 1: 好的,例如,您可以使用 java.util.concurrent.locks .Lock 的实现来实现超时的出队操作,同时授予访问队列的线程公平性。这样的实现是ReentrantLock,它有一个接受公平策略的构造函数。定时tryLock() 支持此属性。您还可以添加一些调试支持来计算队列中的等待线程等。我假设仅使用wait()notify() 来实现这将更加困难。

总而言之,ReentrantLock 在扩展功能上比低级别的同类“更好”。基本行为是相同的。如果您不需要这些额外功能,wait()notify() 仍然是可以接受的替代方案。

【讨论】:

  • 请查看我编辑的问题 - 这不是一个真正相关的答案。
  • 好的,然后我提出一个使用新的高级实用程序 - Lock 的示例建议。
【解决方案3】:

阅读ArrayBlockingQueue 实现的源代码揭示了使用Conditions 作为对象监视器方法“wait/notify/notifyAll”的替代品。此外,使用ReentrantLock 代替“同步”关键字来获得类似的互斥行为和语义。所以看来java.util.concurrent.locks 包就是你要找的。这些新接口更好,因为它们提供了原始同步和锁定结构无法提供的附加功能,例如多个等待集和选择性读取或写入锁(而不是总是同时读取写入)。

java.util.concurrent.atomic 包还提供了对compare-and-swap 指令的接口,这些指令对non-blocking algorithms 很有用,这可能比它们的阻塞替代方案快得多,但也有自己的挑战。

【讨论】:

  • 请查看我编辑的问题 - 这不是一个真正相关的答案。
  • 知道了,这是另一个尝试。
【解决方案4】:
LockSupport 类的

park() unpark() 方法在这种情况下似乎很有用。 我也遇到了同样的问题,在网上搜索时,在这个讨论中找到了线索。

Synchronization vs Lock

但我需要进一步了解这些概念才能创建示例应用程序。

【讨论】:

    【解决方案5】:

    使用 Concurrent 包中的 Semaphore 怎么样? 使用二进制信号量作为内在锁和两个计数信号量来设置队列大小的界限?

    【讨论】:

      猜你喜欢
      • 2020-08-10
      • 2020-10-16
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2015-01-26
      • 1970-01-01
      相关资源
      最近更新 更多