2015-04-07 96 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