【问题标题】:Synchronized Block inside the run methodrun 方法中的同步块
【发布时间】:2013-04-24 00:50:49
【问题描述】:

在 run 方法中使用同步块是否有意义?我认为它确实如此,只要我使用相关的锁,而不是包含此运行方法的 Runnable 实例。阅读 stackoverflow 上类似问题的答案似乎证实了这一点。我尝试编写一些简单的代码来测试它,运行方法中的同步块并不能防止数据损坏:

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);
    }
}

为什么这段代码会产生不正确的结果?这是因为同步块还是其他错误?我觉得我在这里缺少一些基本的东西。

【问题讨论】:

  • 你做对了,and it works correctly
  • 我认为您可能会被 Java 内存模型所吸引。
  • 您使用的是哪个 JRE?
  • 奇怪,我得到的随机结果在 900 到 1000 之间。
  • 使用es.submit()并在返回的future上运行.get()然后打印总和。

标签: java multithreading concurrency synchronized


【解决方案1】:

您的执行程序可能会遇到某种意外错误。如果发生这种情况,您将不会知道,因为您没有得到任何要检查的返回值。

尝试切换到 execute() 的 submit() instead 并存储 Executor 为您提供的 Future 实例列表。如果最终总和小于 1000,则迭代期货并 get() 每个。如果引发异常,您将看到该特定可运行任务发生了什么。

【讨论】:

    【解决方案2】:

    除了看起来不错的简单示例之外,您应该小心 Runnables 中的同步,以防止它们在一个 Runnable 等待某个资源仅由队列中稍后未启动的另一个 Runnable 释放时相互阻塞但是永远不会,因为当前等待的 Runnable 必须首先完成。

    但是,如果有足够的工作线程执行作业,这种情况就不太可能发生。

    【讨论】:

      猜你喜欢
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      • 2022-07-01
      • 2022-12-10
      • 1970-01-01
      相关资源
      最近更新 更多