gpt4 book ai didi

java - 内存与同步互斥锁不一致

转载 作者:搜寻专家 更新时间:2023-11-01 03:38:02 28 4
gpt4 key购买 nike

更新:当我第一次发布这个时,我相当确定代码被破坏了。现在,我不再确定我观察到的是什么。我遇到的最大问题是我似乎无法申请 17.4. Memory Model并直接说明它应该还是不应该起作用。


以下代码已损坏。

它试图实现的目标过于复杂,但此外,它是线程不安全的,因为我观察到它可以无限期地等待 c。我不担心前者(可以使用 ReentrantLockCountDownLatch 来获得更好的代码),但我想知道,后者的原因是什么?

static final ConcurrentHashMap<Integer, Object> mutex = new ConcurrentHashMap<>();


public static brokenFoo() {

Object ourLock = new Object();

for (;;) {
Object theirLock = mutex.putIfAbsent(0, ourLock);
if (theirLock == null) {
break;
}

synchronized (theirLock) { // a
if (mutex.get(0) != theirLock) { // b
continue;
}
theirLock.wait(); // c
} // d
}

try {
// critical section

} finally {
synchronized (ourLock) { // e
mutex.remove(0); // f
ourLock.notifyAll(); // g
} // h
}
}

我考虑过 happens-befores :

  • hb(f, h)hb(h, a) 因此hb(f, a)
  • hb(c, d)hb(d, e) 因此 hb(c, e)

但是,这似乎并不能证明或反驳任何事情。

编辑:(上述问题未能真正解释这段代码应该做什么。)

预期:

  • brokenFoo() 被多个线程调用,上面的代码应该在 //critical section 上提供互斥。
  • 如果两个或多个线程同时进入brokenFoo(),只有一个线程应该进入//critical section,而其他线程则先在某个地方等待。
  • //critical section 中的线程退出后,另一个应该继续取而代之。

实际:

  • 观察到即使没有其他线程在 brokenFoo() 中,也有线程在 c 处等待。

最佳答案

可能是一个线程在另一个线程开始等待() 之前调用notifyAll()。这可能是由于 spurious wakeup 而发生的。 :

  • 线程1进入临界区
  • 线程2开始wait()
  • 线程 2 中发生虚假唤醒
  • 线程1进入同步块(synchronized block)并通知上锁
  • 线程2进入synchronized block ,无限等待

或者线程 1 恰好在线程 2 之前执行。虽然您的代码在 JMM 方面是正确的,但它的 liveness不能保证。这就是为什么您应该使用 CountDownLatch 而不是通知/等待机制。

关于java - 内存与同步互斥锁不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24175558/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com