java - PriorityBlockingQueue 中的锁定/解锁推理可能是什么?

标签 java multithreading blockingqueue

我一直在阅读 source code of PriorityBlockingQueue在 Java 中,我想知道:

  1. 为什么 tryGrow() 方法释放在 offer() 方法中获取的锁,只是为了非阻塞地做它的事情,然后在准备好时再次阻塞替换队列的内容?我的意思是,它本可以保留原来的锁……
  2. 这怎么行?增加队列(涉及数组副本)不会导致并发添加行为不当,当当前添加增加队列大小时,其他添加可能完全出现?

最佳答案

因为内存分配相对较慢并且可以在数组解锁时完成。

通过释放锁,它允许其他线程在分配(可能很大的)新数组时继续运行。

因为这个过程可以在没有锁的情况下完成,所以这样做是一种很好的做法。您应该只持有锁的最短时间。

进行了充分的检查以确保没有其他线程同时执行此操作。

UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, 0, 1)

一次只允许一个线程进入这段代码。

注意

lock.lock();
if (newArray != null && queue == array) {

这会再次获取锁,然后确认它要替换的数组与它在开始时获取的副本相同。如果它同时被替换,那么它只是放弃它刚刚创建的那个,假设其他线程已经增长了数组。

如果仍然相同,则将旧数据复制到新的更大的数组中,然后将其重新种植到田间。

作为Kamil很好地解释。

Purpose of that unlock is only to be sure that the faster thread will grow the queue, so we will not waste time while locking the "better ones".

关于java - PriorityBlockingQueue 中的锁定/解锁推理可能是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41347205/

相关文章:

java - 跨不同网络访问 infinispan 缓存

c# - WPF C# 从 App 调用窗口函数

c - 通过条件变量唤醒的线程何时运行?

java - 如何在Spring TaskExecutor框架中管理线程

java - 使用新的与正常的减速和整数的性质来声明变量(装箱/拆箱)

java - Java 8 的 forEachOrdered() 和 sequential() 方法之间的区别?

Java Double Format即使为零也显示2个小数点

c# - 非阻塞并发收集?

java - 取前如何查看BlockingQueue头元素?

Python:Kombu+RabbitMQ Deadlock——队列不是阻塞就是阻塞