我想使用Swap函数解决互斥问题,但程序遇到死锁,我不知道为什么。当一个线程连续执行两次时,似乎会出现问题。
交换锁定逻辑:
每个线程都使用本地变量和共享变量。 线程首先锁定其本地变量(例如假设1值)。 当一个线程本地变量被解锁时(例如假设0值)它可以执行临界区,如果线程 local 变量被锁定(例如假定为1),则该线程为在忙等待(繁忙等待测试本地变量解锁并调用 swap 功能)
交换功能将本地变量设置为共享变量值,反之亦然。交换功能必须是ATOMIC。
当线程调用swap时,如果交换后“共享”变量为0(解锁),则 shared 变量为1, local 为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;
}
}
答案 0 :(得分:0)
想象一下这种情况:
shared.setVar(local.getVar());
(现在为shared_var == 1)和local.setVar(temp);
(请记住步骤2中的temp为1)。已经产生死锁:shared_var为1,并且临界区中没有线程。这是因为SWAP不是原子的(监视器可以远离执行同步方法的线程,它只是不允许其他线程进入这样的方法,也不允许其他方法在同一个锁上同步(在静态方法的情况下类) ,在非静态方法的情况下对象的实例))。
为了解决这个问题,你不应该在执行SWAP时允许共享更改,方法是找到使其成为原子的方法。一种可能性是摆脱本地化,并在compareAndSet上使用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);
}
}
}