【问题标题】:Is CyclicBarrier.getNumberWaiting() accurate?CyclicBarrier.getNumberWaiting() 准确吗?
【发布时间】:2020-02-29 13:23:07
【问题描述】:

我分析了jdk1.8中的代码,但在其他jdk版本中可能有同样的问题

  1. 让我们假设以下代码中的 party = 3

    CyclicBarrier cb = new CyclicBarrier(3);

parties = 3 and count > = 0,所以getNumberWaiting()的返回值 但在某些特定情况下,超过 3 个线程会在等待 2.看看CyclicBarrier中的关键代码

a) 位置 2 的线程 A 将返回 0,现在 有 2 个线程 在位置 3 等待

b) 线程 A 执行 lock.unlock() 后,位置 1 的线程 B 获得了锁(但是锁是不公平的),所以现在 index = 2,count = 2,它会在位置 3 等待,所以现在位置 3 有 3 个线程等待

c) 假设,锁总是被位置1的线程获取,所以等待线程的数量会越来越多

所以 getNumberWaiting() > 3 就是结果

getNumberWaiting() = (循环数) * 参与方 - 计数

【问题讨论】:

  • 不要将代码粘贴为图像。它使得无法复制/粘贴以进行测试,并且由于它是文本,因此不需要是图像(我相信您可以想出一个与红色大箭头不同的指示器来显示错误所在)。
  • 您是否遇到错误,或者您是否声称存在基于对自 1.5 以来 JDK 中的类的眼睛分析的错误?
  • 这是一个基于眼睛分析的bug讨论,我只是想收集支持者
  • @Kayaman 这个问题只是讨论和眼睛分析,所以我认为粘贴代码作为图像是合适的
  • 那么这不是错误。除非你能展示导致错误行为的代码,否则只是你不理解它为什么起作用。

标签: java java.util.concurrent cyclicbarrier


【解决方案1】:

我认为您需要多看一下“世代”的概念。在您的场景中,线程 A 将调用 nextGeneration() 重置所有计数 (getNumberWaiting() = 0) 并向所有 当前 服务员发出信号。那些服务员(现在的上一代)将很快开始完成。

所以是的,可能有超过 3 个线程针对 trip 条件,但 2 x 旧服务员已发出信号离开,任何新服务员都在等待新信号。 getNumberWaiting 不是使用 Lock.getHoldCount() 计算的,所以可以。

【讨论】:

  • nextGeneration()会调用trip.signalAll(),但是这个方法不能让线程在拿到锁之前离开,但是我们可以假设锁总是在位置1被抓取,所以等待线程将累积在位置 3
  • 只有被执行LockSupport.unpark()的线程才能继续,否则会一直阻塞在位置3,trip.signalAll()不能解除线程
  • 确实,“老服务员”可能需要等待新服务员入睡才能竞争,但这只是描述了锁的公平性。你说的和我的回答还是一样的。 内部锁上的服务员数量可以>3,但CyclicBarriers合约保持不变,因为它们是不同代的。
  • 你的意思是getNumberWaiting() = getNumberWaitOfCurrentGeneration(), getTotalNumberWaiting() = 所有正在等待的线程?
  • 正是如此。我认为您不应该提交 jdk 错误!
猜你喜欢
  • 2011-04-10
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
相关资源
最近更新 更多