2013-05-08 103 views
3

不確定此D類線程是否正確。是否存在競態條件,i應該在訪問時處於同步塊中?如果D是外部類,並且A實例被傳遞給了D構造函數呢?Java同步線程

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

完全無關,正如其他人似乎已經涉及到的,但延長'線程'被認爲是不好的做法。 – pickypg 2013-05-08 06:13:37

+0

谷歌開發人員一直在android示例代碼中執行此操作! – 2013-05-08 06:14:32

+3

下面是[更好的方法](http://stackoverflow.com/questions/1921514/how-to-run-a-runnable-thread-in-android)。這樣,你不會發現自己意外地壓倒性的東西,也不會帶着你不需要的額外記憶包袱。 – pickypg 2013-05-08 06:19:15

回答

1

只要您只調用f一次,這是安全的。在數據變異的線程A和從線程A開始的線程B(HB關係在Thread.start)之間有一個發生在前的關係。由於D啓動後沒有人變更數據,因此這是安全的。

一些打破線程安全的方法:再次

  • 發生變異i,包括再次調用foo
  • 從比D其他線程或調用foo

一讀i你不能再次改變i的原因是,即使是從調用foo的線程,也是這個變種會有hav e發生在d.start()之後,因此對於第二次突變沒有HB邊緣。

你不能從任意線程讀取i的原因是,這個線程不會有一個明確的了i++突變的看法。

它可以比這更微妙,但在高層次,你去。

1

有一個競爭條件?

可能如果從一個以上的線程調用f像您沒有適當同步地訪問共享變量(i)。

但請注意,啓動線程會創建一個發生之前的關係

所以g將等於i值線程啓動權之前(即當d.start()被稱爲i值),或者如果i任何後續值已被在此期間另一個線程修改(不保證這種修改實際上是可見的)。

1

如果f()會從一個被調用,並在同一個線程不會有問題,因爲start()保證irun()run()可見不改變i。否則,您需要AtomicInteger或​​。請注意,只需volatile i不會幫助,一些i++可能會丟失。