簡體   English   中英

Java-使用SWAP功能解決互斥的死鎖

[英]Java - Deadlock using SWAP function to solve mutual exclusion

我想使用Swap函數解決互斥問題,但是該程序存在死鎖,而且我不知道為什么。 當線程連續兩次執行時,似乎會出現問題。

交換鎖邏輯:

每個線程都使用局部變量和共享變量。 線程首先鎖定其局部變量(例如,假定值為1)。 當線程局部變量被解鎖(例如,假設值為0)時,它可以執行關鍵部分,如果線程局部變量被鎖定(例如,假設值為1),則線程處於繁忙等待狀態 (繁忙等待測試了局部變量的解鎖)並調用交換功能)

swap函數將局部變量設置為共享變量值,反之亦然。swap函數必須為ATOMIC。

當線程調用交換時,如果交換后“共享”變量為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);
}
...
}

共享變量類

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. 第一個線程交換本地和shared_var。 現在shared_var為1,local為0。
  2. 由於SWAP上的同步是在Synch類上的,因此第一個線程使用SWAP完成后,線程2即可進入。 線程2使temp = 1,這時監視器切換回線程1。
  3. 線程1完成循環的第一次迭代,打印exec消息並離開關鍵部分並設置shared_var =0。監視器移至線程2。
  4. 線程2繼續進行SWAP。 它留在哪里。 它執行shared.setVar(local.getVar()); (現在shared_var == 1)和local.setVar(temp); (請記住,步驟2中的temp為1)。

產生了死鎖:shared_var為1,並且臨界區中沒有線程。 這是因為SWAP不是原子的(監視器可以從執行同步方法的線程中移開,它只會不允許其他線程進入該方法,也不允許其他方法在同一鎖上同步(對於靜態方法而言,該類為此類) ,如果是非靜態方法,則為對象的實例))。

為了解決此問題,您不應該允許SWAP執行時更改共享,方法是使其成為原子的。 一種可能是擺脫局部,並在AtomicBoolean上使用compareAndSet ,該AtomicBoolean目前將扮演shared_var的角色。

原子類型保證原子性和揮發性(請參閱文檔 )。 這樣,每個線程都應該獲取用於信號發送的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);
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM