2015-11-01 55 views
0

以下是從Java concurrency in Pratice開始的第一個代碼段。我不明白這個類是不是線程安全的?每次線程都不需要調用方法getNext()時,它會首先創建此類的實例?兩個線程可以共享這個類的同一實例(barring explicit share)?線程安全:類的實例

@NotThreadSafe 
public class UnsafeSequence { 
private int value; 
/** Returns a unique value. */ 
public int getNext() { 
return value++; 
} 
} 

回答

3

我不明白這個類是不是線程安全的?

你可能已經現在這個問題的答案,但我在這裏包括它的完整性。)

的問題是value++聲明。這是一個多部分的聲明。

  1. 讀取value的值。
  2. 讀取的值增加1。
  3. 新值存儲在value

該序列可以被另一個線程混合使用。說value5。如果兩個線程調用getNext()(在同一個實例中),那麼在完成後,您會預計value7。然而,如果兩個線程以前任何線程完成步驟1和2做第3步,他們都將寫入值6value

  • 線程1做第1步 - 讀取5
  • 線程2做步驟1 - 將讀取5
  • 線程2執行步驟2 - 由1
  • 線程2做步驟3增量5 - 保存的值6
  • 線程1做步驟2 - 增量5通過1
  • 線程1做第3步 - 保存6

就不會在每次一個線程需要調用該方法GETNEXT()的時候,它會 首先創建的這個實例值類?

不是每一次。這將是new UnsafeSequence().getNext()一遍又一遍,這是沒有道理的。但也許這不完全是你的意思。每個線程都可以擁有自己的類實例,並且可以調用getNext()。在那種情況下,沒有問題。

兩個線程可以共享這個類的同一實例(除非明確 份額)?

不,必須以某種方式共享實例。但它可以在你不知情的情況下共享。例如,某些類可能有一個返回UnsafeSequence實例的static方法。你不知道它是否是每次都返回的實例,或者每次調用都創建一個新實例。 除非這是記錄在某處。


有關API文檔中類是否線程安全的討論,指的是在線程之間共享實例的情況。如果一個實例不共享,則可以在多線程應用程序中使用它,只需,因爲它只有一個線程可用。

1

是明顯的2個或更多的線程可以同時訪問同一個對象。即當競爭條件發生時,即當多於一個線程爭用共享資源時(在您的情況下爲UnsafeSequence的同一對象)。

EG:

UnsafeSequence seq = new UnsafeSequence(); 
// both thread instances share same object 
Thread t1 = new MyThread(seq); 
Thread t2 = new MyThread(seq); 
t1.start(); 
t2.start(); 

// run method for above `MyThread` class: 
public void run() { 
    while(some condition) { 
    // some work 
    System.out.println(seq.getNext()); // sequence is unpredictable 
    } 
} 

有不同的線程訪問,不同對象實例,就沒有線程安全問題。

+0

我無法在那裏看到顯而易見的內容。謹慎地解釋這個問題的背景? – Forkmohit

+0

謝謝。我明白什麼時候「分享」,見我問題的最後一句話。 – Forkmohit

+0

對不起,我沒有得到最後一部分。你能否詳細說明一下。 –

0

由於Java允許多線程語言(其中多個線程並行運行以完成程序執行) 在多線程環境中,Java對象的同步或Java類的同步變得非常重要。

同步是一個功能,它允許一次只有一個線程可以訪問資源。它適用於鎖定的概念。

ThreadDemo T1 = new ThreadDemo(safeSeq); 
    ThreadDemo T2 = new ThreadDemo(safeSeq); 

在上面的代碼中,我們準備了兩個線程

這裏單獨鎖
public class UnsafeSequence { 
private int value; 
/** Returns a unique value. */ 
public int getNext() { 
return value++; 
    } 
} 


class ThreadDemo extends Thread { 

UnsafeSequence safeSeq; 

public void run() { 

some code here 

safeSeq.getNext(); 

} 

} 

public class TestThread { 
public static void main(String args[]) { 

    UnsafeSequence safeSeq = new UnsafeSequence(); 

    ThreadDemo T1 = new ThreadDemo(safeSeq); 
    ThreadDemo T2 = new ThreadDemo(safeSeq); 

    T1.start(); 
    T2.start(); 

    } 
} 
1

兩個線程可以共享這個類(除明確股)的同一個實例?

我認爲這是你誤解的根源。

基本上,如果兩個線程都使用給定實例的引用,他們正在共享該實例。他們如何設法掌握參考並不重要。 「明確」和其他分享參考方式之間沒有真正的區別。

而這個例子的基本假設是兩個線程> do <以某種方式管理共享實例。如果他們沒有,或者確實只有一個線程,那麼線程的安全性或其他類不會成爲問題。使用Goetz等人的術語,線程安全性「線程限制」對象無關緊要。)