3

不确定这个 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;
        }
    }
}
4

3 回答 3

1

有比赛条件吗?

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

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

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

于 2013-05-08T06:05:26.233 回答
1

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

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

  • 再次变异i,包括foo再次调用
  • 从调用i的线程以外的线程读取Dfoo

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

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

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

于 2013-05-08T06:10:51.963 回答
1

如果f()将从同一个线程调用,则不会有问题,因为start()保证i从可见run()run()不会更改i。否则你需要AtomicIntegeror synchronized。请注意,根本volatile i无济于事,有些i++可能会丢失。

于 2013-05-08T06:20:41.137 回答