在run方法中使用synchronized块是否有意义?我认为它确实如此,只要我使用相关的锁,而不是包含此run方法的Runnable实例。在stackoverflow上阅读类似问题的答案似乎证实了这一点。我试着编写一些简单的代码来测试它,并且run方法中的synchronized块不会阻止数据损坏:
public class Test {
public Test() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
es.execute(new Runnable() {
@Override
public void run() {
synchronized (lock) {
sum += 1;
}
}
});
}
es.shutdown();
while(!es.isTerminated()) {
}
}
private int sum = 0;
private final Object lock = new Object();
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.sum);
}
}
为什么此代码会生成错误的结果?这是因为同步块还是其他一些错误?我觉得我在这里缺少一些基本的东西。
答案 0 :(得分:1)
您的执行程序可能会遇到某种意外错误。如果发生这种情况,你就不会知道它,因为你没有得到任何返回值来检查。
尝试切换到execute {的submit() instead并存储Executor为您提供的Future个实例列表。如果最终总和小于1000,则迭代期货并获得每个期货。如果出现异常,您将看到该特定runnable任务发生了什么。
答案 1 :(得分:1)
除了你看起来不错的简单例子之外,你应该注意Runnables中的同步,以防止它们在一个Runnable等待某个资源仅由稍后未在队列中运行的另一个Runnable释放时阻止彼此阻塞但是从现在开始等待Runnable必须先完成。
但是,如果有足够的工作线程执行作业,则不太可能发生这种情况。