2009-07-16 60 views
2

我在與同步行爲不我所期望的方式問題,我使用volatile關鍵字嘗試也:的Java同步問題

共享對象


public class ThreadValue { 
private String caller; 
private String value; 
public ThreadValue(String caller, String value) { 
    this.value = value; 
    this.caller = caller; 
} 

public synchronized String getValue() { 
    return this.caller + "  " + this.value; 
} 
public synchronized void setValue(String caller, String value) { 
    this.caller = caller; 
    this.value = value; 
} 
} 

主題1:


class CongoThread implements Runnable { 
    private ThreadValue v; 
    public CongoThread(ThreadValue v) { 
    this.v = v; 

    } 
    public void run() { 
    for (int i = 0; i 10; i++) { 
    v.setValue("congo", "cool"); 
    v.getValue(); 
    } 
    } 
} 

主題2:


class LibyaThread implements Runnable { 
    private ThreadValue v; 
    public LibyaThread(ThreadValue v) { 
    this.v = v; 

    } 
    public void run() { 
    for (int i = 0; i 10; i++) { 
     v.setValue("libya", "awesome"); 
     System.out.println("In Libya Thread " + v.getValue()); 

    } 
    } 
} 

調用類:


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

    ThreadValue v = new ThreadValue("", ""); 
     Thread congo = new Thread(new CongoThread(v)); 
     Thread libya = new Thread(new LibyaThread(v)); 

    libya.start(); 
     congo.start(); 

    } 
} 

偶爾我得到「在利比亞主題剛果酷」 這絕不應該發生。我只希望: 「在利比亞線程利比亞真棒」 「在剛果線程剛果酷」

我不指望他們混合。

回答

5

的呼叫可以交錯類似如下:

Thread 1 : v.setValue() 
Thread 2 : v.setValue() 
Thread 1 : v.getValue() // thread 1 sees thread 2's value 
Thread 2 : v.getValue() // thread 2 sees thread 2's value 
3

這可能是在這個秩序,這是正確的:

v.setValue("libya", "awesome"); 
//context switch 
v.setValue("congo", "cool"); 
//context switch 
System.out.println("In Libya Thread " + v.getValue()); 

因此你必須在某些意義的比賽條件。無論何時嘗試調用同步方法,Synchronized都會獲得一個鎖,因此您需要另一種方法來暗示同步訪問變量。例如,您可以從方法移除所有同步並執行以下操作:

public void run() 
{ 
    for (int i = 0; i 10; i++) 
    { 
    synchronized(v) 
    { 
     v.setValue("caller", "value"); 
     v.getValue(); 
    } 
    } 
} 
3

到的getValue()和setValue方法(的呼聲)可交錯。

也就是說,沒有線程同時在getValue()中,同時另一個線程在getValue()或setValue()中,同樣沒有線程在setValue()中,而另一個線程在getValue()或setValue ()。

但是,不能保證單個線程將順序調用setValue()getValue()而不被其他線程搶佔。

基本上,這是完全合法的和可能的:

線程1:v.setValue()
其他線程(S):任何數量的v.getValue()的/ v.setValue ()的
主題1:v.getValue()

4

這應該讓你找到你想要的行爲。

主題1:

class CongoThread implements Runnable { 
    private ThreadValue v; 

    public CongoThread(ThreadValue v) { 
     this.v = v; 
    } 

    public void run() { 
     for (int i = 0; i < 10; i++) { 
      synchronized(v) { 
       v.setValue("congo", "cool"); 
       System.out.println("In Congo Thread " + v.getValue()); 
      } 
     } 
    } 
} 

線程2:

class LibyaThread implements Runnable { 
    private ThreadValue v; 

    public LibyaThread(ThreadValue v) { 
     this.v = v; 
    } 

    public void run() { 
     for (int i = 0; i < 10; i++) { 
      synchronized(v) { 
       v.setValue("libya", "awesome"); 
       System.out.println("In Libya Thread " + v.getValue()); 
      } 
     } 
    } 
} 
+1

在一個不平凡的程序,你可能想隱瞞甚至這個水平同步。有一個像setValueAndReturnString()它自己同步的方法。你不想依賴調用者正確處理多線程。 – AngerClown 2009-07-16 19:00:05