2015-04-07 103 views
1

我想通過Swap函數解決互斥問題,但程序遭受死鎖,我不知道爲什麼。這似乎是一個線程exec連續兩次發生的問題。Java - 使用SWAP函數解決互斥問題的死鎖

交換鎖邏輯:

每個線程化妝使用本地可變的和共享變量。 線程首先鎖定其本地變量(例如,假定1個值)。 當一個線程本地變量被解鎖(例如假設0的值),它可以執行該臨界區,如果線程本地變量被鎖定(例如假設值爲1)的線程處於忙着等待(該忙等待測試本地變量解鎖並調用交換功能)

交換函數設定本地變量到共享變量值和viceversa.The交換功能必須是原子的。

當一個線程呼叫交換,如果「共享」的變量交換後爲0(解鎖),我們有共享變量是1和本地爲0 因此,只有該線程可以訪問到關鍵部分沒有其他人。

最後(沒有更多關鍵部分)線程解鎖共享變量。

public class Mutex { 

    public static void main(String []args){ 
     LockVar var = new LockVar(0); 
     ThreadSwap th0 = new ThreadSwap(var); 
     ThreadSwap th1 = new ThreadSwap(var); 
     ThreadSwap th2 = new ThreadSwap(var); 
     th0.start(); 
     th1.start(); 
     th2.start(); 
    } 
} 

線程類

class ThreadSwap extends Thread{ 

    private LockVar shared_var; 

    public ThreadSwap(LockVar var){ 
    this.shared_var = var; 
    } 
    @Override 
    public void run(){ 
     LockVar local = new LockVar(1); 
     while(true){ 
     ---> local.setVar(1); 
     ---> while(local.getVar() == 1){Synch.SWAP(shared_var, local);} 
      System.out.println("Thread " + getId() + " exec critical section."); 
      // Critical section 
      System.out.println("Thread " + getId() + " is leaving critical section."); 
     ---> shared_var.setVar(0); 
     } 
    } 
} 

交換功能(這種類型的互斥鎖強調的邏輯)

class Synch{ 
public static synchronized void SWAP(LockVar shared, LockVar local){ 
    int temp = shared.getVar(); 
    shared.setVar(local.getVar()); 
    local.setVar(temp); 
} 
... 
} 

共享VAR類

class LockVar{ 
private volatile int var; 
public LockVar(int value){ 
    this.var = value; 
} 
public int getVar(){ 
    return this.var; 
} 
public void setVar(int value){ 
    this.var=value; 
} 

}

+1

什麼是ThreadTaS? – user2891462

+0

預期結果是什麼?你得到的實際結果是什麼? 請注意,您在每個循環的末尾以非同步的方式使用setVar。 – user2891462

+0

對不起,我將編輯正確的代碼.. – MadDogTannen

回答

0

想象一下這樣的情景:

  1. 第一螺紋互換本地和shared_var。現在shared_var是1並且本地是0.
  2. 由於SWAP上的同步在Synch類上,所以只要第一個線程完成了SWAP,線程2就可以進入它。線程2使temp = 1,此時監視器切換回線程1.
  3. 線程1完成循環的第一次迭代,打印exec消息並保留臨界區並設置shared_var = 0。線程2。
  4. 線程2進行交換。它離開它。它執行shared.setVar(local.getVar());(現在爲shared_var == 1)和local.setVar(temp);(記住步驟2中的temp爲1)。

產生了死鎖:shared_var是1,沒有線程在關鍵部分。這是因爲SWAP不是原子的(監視器可以從執行同步方法的線程移開,它不會允許其他線程進入此方法,也不允許其他方法在同一個鎖上同步(在靜態方法的情況下爲類) ,在非靜態方法情況下的對象實例))。

爲了解決這個問題,你不應該允許在執行SWAP時共享改變,通過找到使它成爲原子的方式。一種可能性是擺脫本地並使用在AtomicBoolean這會扮演shared_var的角色。

原子類型保證原子性和揮發性(見documentation)。這樣一來,每個線程應該得到一個參考(原諒我鬆散的術語),以用於信令的AtomicBoolean和使用compareAndSet原子地更新的方式變量的值是立即可見的其他線程:

import java.util.concurrent.atomic.AtomicBoolean; 

public class Mutex { 

    public static void main(String []args){ 
    AtomicBoolean isLocked = new AtomicBoolean(false); 
    ThreadSwap th0 = new ThreadSwap(isLocked); 
    ThreadSwap th1 = new ThreadSwap(isLocked); 
    ThreadSwap th2 = new ThreadSwap(isLocked); 
    th0.start(); 
    th1.start(); 
    th2.start(); 
    } 
} 

class ThreadSwap extends Thread { 

    private AtomicBoolean shared_IsLocked; 

    public ThreadSwap(AtomicBoolean var){ 
    this.shared_IsLocked = var; 
    } 

    @Override 
    public void run(){ 
    while(true){ 
     // While the flag is true (locked), keep checking 
     // If it is false (not locked), atomically change its value and keep going 
     while(!shared_IsLocked.compareAndSet(false, true)); 
     System.out.println("Thread " + getId() + " exec critical section."); 
      // Critical section 
     System.out.println("Thread " + getId() + " is leaving critical section."); 
     shared_IsLocked.set(false); 
    } 
    } 
} 
+0

非常感謝,你幫助我提高了我對顯示器的認識。所以這是一個解決方案: ** Thread Class ** ... ... ... Synch.SET(shared_var,0); ... **同步類** '類同步{ 公共同步靜態無效SET(LockVar共享,int值){ shared.setVar(值); } public synchronized static void SWAP(LockVar shared,LockVar local){int} temp = shared.getVar(); shared.setVar(local.getVar()); local.setVar(溫度); }' – MadDogTannen