我有两个同步的代码块。我需要两个代码块才能在两个或多个不同的线程中同时运行,但我会喜欢允许两个或更多个不同的线程运行一个同时代码块。如何在Java中完成?举例说明:
class HelloWorld {
method1() {
synchronized (?) { //block 'A'
//I want to allow 2+ threads to run this code block simultaneously
}
}
method2() {
synchronized (?) { //block 'B'
//this should block while another thread is running
//the synchronized block 'A'
}
}
我不希望两个同步块都锁定在同一个对象/类上,因为这会阻止第一个块同时由多个线程运行。但是,这是我所知道的唯一一种防止块A和B同时由2个或多个线程运行的方法。必须有办法实现这一目标。
答案 0 :(得分:2)
我建议分别查看ReadWriteLock实施班ReentrantReadWriteLock。这个东西特别设计为允许多个“读者”线程;但只有一个“作家”主题。
如果我正确地阅读了您的问题,那正是您所要求的。另一方面,退一步说明你想在这里解决的真正的问题也许是明智之举。
特别是考虑到前面提到的锁与Java8很好地兼容,但在早期版本的Java中看到了问题。
答案 1 :(得分:0)
可能是这样的:
private CommonStateSynchronizer synchronizer = new CommonStateSynchronizer();
public void method1() throws InterruptedException
{
synchronizer.run("method1", () -> {
// do method1
});
}
public void method2() throws InterruptedException
{
synchronizer.run("method2", () -> {
// do method2
});
}
public static class CommonStateSynchronizer
{
private final ReentrantReadWriteLock rw;
private final ReentrantReadWriteLock.ReadLock r; // hold read lock while executing in current state
private final ReentrantReadWriteLock.WriteLock w; // hold write lock while checking or changing state
private final Condition stateChanged;
private volatile String currentState; // do not modify unless holding write lock
public CommonStateSynchronizer()
{
rw = new ReentrantReadWriteLock(true);
r = rw.readLock();
w = rw.writeLock();
stateChanged = w.newCondition();
}
public void run(String state, Runnable runnable) throws InterruptedException {
w.lock();
while (!state.equals(currentState))
{
if (currentState == null)
{
currentState = state;
stateChanged.notifyAll();
break;
}
stateChanged.await();
}
assert state.equals(currentState);
// downgrade to concurrent read lock
r.lock();
w.unlock();
try
{
runnable.run();
}
finally
{
r.unlock();
w.lock();
if (rw.getReadLockCount() == 0)
{
currentState = null;
stateChanged.notifyAll();
}
w.unlock();
}
}
}