【发布时间】:2014-06-12 02:26:42
【问题描述】:
更新: 当我第一次发布这个时,我相当确定代码被破坏了。现在,我不再确定我观察到了什么。我遇到的最大问题是我似乎无法申请 17.4. Memory Model 并直接说明它应该还是不应该工作。
以下代码已损坏。
它试图实现的目标过于复杂,但此外,它是线程不安全的,因为我观察到它可以无限期地等待c。我不担心前者(可以使用ReentrantLock 或CountDownLatch 以获得更合理的代码),但我想知道后者的原因是什么?
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处等待。
【问题讨论】:
-
你能解释一下你想用这段代码实现什么吗?
-
通过上面的代码,我想以最简单的方式说明上述问题,以便我可以输入关于互斥和内存一致性方面的错误.这样我可以更好地理解
synchronized的工作原理和不工作原理,以及 Java 内存模型的规定,以便我可以在未来的案例中应用这些常识。 -
是的,但您的期望是什么?这个方法是多线程调用的?它应该怎么做?它实际上是做什么的?它只是在
cwait()上阻塞? -
对不起,我明白你的意思了。我已经修改了问题。
-
@Voo: 重新排序
remove和notify不应该有任何显着影响,因为这些操作在synchronized块内,因此 atomic 用于同步的其他线程同一个对象。
标签: java multithreading synchronization