我尝试了一些使用更高级别构造的尝试,但没有想到任何事情.我认为这可能是一个下降到低级API的机会:
EDIT: I actually think you’re trying to set up a problem which is inherently tricky (see second to last paragraph) and probably not needed (see last paragraph). But that said, here’s how it could be done, and I’ll leave the color commentary for the end of this answer.
private int someMethod1Invocations = 0;
private int someMethod2Invocations = 0;
public void someMethod1() {
synchronized(this) {
// Wait for there to be no someMethod2 invocations -- but
// don't wait on any someMethod1 invocations.
// Once all someMethod2s are done, increment someMethod1Invocations
// to signify that we're running, and proceed
while (someMethod2Invocations > 0)
wait();
someMethod1Invocations++;
}
// your code here
synchronized (this) {
// We're done with this method, so decrement someMethod1Invocations
// and wake up any threads that were waiting for that to hit 0.
someMethod1Invocations--;
notifyAll();
}
}
public void someMethod2() {
// comments are all ditto the above
synchronized(this) {
while (someMethod1Invocations > 0)
wait();
someMethod2Invocations++;
}
// your code here
synchronized(this) {
someMethod2Invocations--;
notifyAll();
}
}
上面的一个明显问题是它可以导致thread starvation.例如,someMethod1()正在运行(并阻塞someMethod2()s),就在它即将完成时,另一个线程出现并调用someMethod1().进行得很好,就像它完成另一个线程启动someMethod1(),依此类推.在这种情况下,someMethod2()永远不会有机会运行.这实际上并不是上述代码中的错误;这是您的设计需求的一个问题,一个好的解决方案应该积极解决.我认为公平AbstractQueuedSynchronizer可以做到这一点,尽管这是一个留给读者的练习. ?
最后,我无法抗拒但是插入一个意见:鉴于ConcurrentHashMap操作非常快,你可能最好只是在两个方法中放置一个互斥锁并完成它.所以是的,线程必须排队以调用someMethod1(),但是每个线程都会非常快速地完成它(因此让其他线程继续).这应该不是问题.