sho*_*301 7 java multithreading
我正在学习Java多线程编程.我有一个以下逻辑:
假设我有一个A类
class A {
ConcurrentMap<K, V> map;
public void someMethod1 () {
// operation 1 on map
// operation 2 on map
}
public void someMethod2 () {
// operation 3 on map
// operation 4 on map
}
}
Run Code Online (Sandbox Code Playgroud)
现在我不需要同步"someMethod1"或"someMethod2"中的操作.这意味着如果有两个线程同时调用"someMethod1",我不需要序列化这些操作(因为ConcurrentMap将完成这项工作).
但是我希望"someMethod1"和"someMethod2"是彼此的互斥,这意味着当某个线程正在执行"someMethod1"时,另一个线程应该等待进入"someMethod2"(但是应该允许另一个线程进入"someMethod1").
那么,简而言之,有没有一种方法可以让"someMethod1"和"someMethod2"不是互相的互斥体而是互相的互斥体?
我希望我说的问题足够明确......
谢谢!
我尝试了几次更高级别的构造,但什么也没想到。我认为这可能是一个深入了解低级 API 的机会:
编辑:我实际上认为你正在尝试设置一个本质上很棘手的问题(参见倒数第二段)并且可能不需要(参见最后一段)。但话虽如此,这就是如何做到这一点,我将在这个答案的末尾留下颜色评论。
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();
}
}
Run Code Online (Sandbox Code Playgroud)
上述一个明显的问题是它可能导致线程饥饿。例如,someMethod1()正在运行(并阻塞someMethod2()),就在它即将完成时,另一个线程出现并调用someMethod1()。一切进展顺利,就在它完成时另一个线程启动someMethod1(),依此类推。在这种情况下,someMethod2()永远不会有机会逃跑。这实际上并不是上面代码中的直接错误;而是错误。这是一个与您的设计需求相关的问题,一个好的解决方案应该积极努力解决这个问题。我认为一个公平的AbstractQueuedSynchronizer可以做到这一点,尽管这是留给读者的练习。:)
最后,我忍不住要插入一个观点:鉴于ConcurrentHashMap操作非常快,您最好只在这两个方法周围放置一个互斥体并完成它。所以,是的,线程必须排队才能调用someMethod1(),但每个线程都会非常快地完成其轮次(从而让其他线程继续进行)。这应该不是问题。