我想同步通过ExecutorService调用的3个线程。如何确保它们在同一个对象上同步?
现在我有了这段代码:
class Test {
executor.submit(new Request(threadNames[i]));
executor.submit(new Request(threadNames[i]));
executor.submit(new Request(threadNames[i]));
private class Request implements Callable {
@Override
public Long call() throws InterruptedException {
if (threadName.equals("SOMETHING") {
doSomething();
} else {
doSomeOtherThing();
}
}
}
private synchronized void doSomething() {
}
private synchronized void doSomeOtherThing() {
}
...
}
其中一个线程负责生成一个条件,另一个线程负责它。
答案 0 :(得分:1)
您无法将线程提交给Executor服务;你提交 tasks ,稍后会在Executor的线程池中的一个线程上执行;
如果一个任务是生产者而另外两个是消费者,则将所有三个任务提交给执行者是错误的。它很容易导致死锁,消费者任务无限期地等待生产者,但生产者无法运行,因为消费者占据了所有线程。
重新考虑您的解决方案,以便生产者任务还负责将消费者任务提交给执行者;任务可以使用生成的值进行实例化,因此协调问题在一开始就得到了解决。
答案 1 :(得分:0)
根据文件(http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html):
每个对象都有一个与之关联的内在锁。按照惯例, 需要对对象进行独占和一致访问的线程 fields必须在访问之前获取对象的内部锁 它们,然后在它们完成时释放内在锁。一个 据说线程拥有它之间的内在锁定 获得了锁并释放了锁。
当线程调用synchronized方法时,它会自动获取 该方法的对象的内在锁定,并在该方法时释放它 方法返回。即使返回发生,也会发生锁定释放 一个未被捕获的例外。
您可能想知道静态同步方法会发生什么 调用,因为静态方法与类关联,而不是 宾语。在这种情况下,线程获取内部锁 与类关联的类对象。从而访问类的静态 字段由锁定控制,该锁定与任何锁定不同 班级的实例。
所以你的方法正在使用来自Test
对象的内部锁定,是的,正如Marko正确指出的那样,你可能会陷入僵局。