【问题标题】:Java synchronized threadJava同步线程
【发布时间】:2013-05-08 06:03:19
【问题描述】:

不确定这个 D 类线程是否正确。是否存在竞争条件,i 在访问时是否应该在同步块中?如果 D 是外部类,并且 A 实例被传递给 D 构造函数怎么办?

class A
{
    int i;
    void f() {
        i++;
        D d = new D();
        d.start();
    }
    class D extends Thread {
        public void run() {
            int g = i;
        }
    }
}

【问题讨论】:

  • 完全不相关,因为其他人似乎已经涵盖了您,但扩展 Thread 被认为是不好的做法。
  • Google 开发人员一直在 android 示例代码中这样做!
  • 这是better approach。这样你就不会发现自己意外地覆盖了一些东西,也不会携带很多你不需要的额外记忆包袱。
  • 按原样,完全没有问题。在启动线程之前增加i,并且根本没有线程修改i

标签: java multithreading java.util.concurrent


【解决方案1】:

只要您只调用一次f,这是安全的。在改变数据的线程 A 和从线程 A 启动的线程 B 之间存在先发生关系(HB 关系位于 Thread.start)。由于在D 启动后没有人改变数据,所以这是安全的。

一些破坏线程安全的方法:

  • 再次改变i,包括再次调用foo
  • 从除D 或调用foo 的线程之外的线程读取i

即使是从调用foo 的线程也不能再次变异i 的原因是,这种变异将发生在d.start() 之后,因此对于第二个变异没有HB 优势。

您无法从任意线程读取i 的原因是该线程没有明确定义的i++ 突变视图。

它可能比这更微妙,但在高层次上,你去吧。

【讨论】:

    【解决方案2】:

    如果f() 将从同一个线程调用,则不会有问题,因为start() 保证irun() 可见,并且run() 不会改变i。否则你需要AtomicIntegersynchronized。请注意,简单的volatile i 将无济于事,一些i++ 可能会丢失。

    【讨论】:

      【解决方案3】:

      有竞争条件吗?

      如果您从多个线程调用 f,可能会因为您访问共享变量 (i) 而没有正确同步。

      但请注意,启动线程会创建先发生关系

      所以g 将等于在线程启动之前i 的值(即,当d.start() 被调用时i 的值)或任何后续值,如果i 已被修改与此同时,另一个线程(不保证实际看到此类修改)。

      【讨论】:

        猜你喜欢
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多