[英]Java - Deadlock using SWAP function to solve mutual exclusion
I would like to solve mutual exclusion using the Swap function but the program suffer from deadlock and I don't know why. 我想使用Swap函数解决互斥问题,但是该程序存在死锁,而且我不知道为什么。 It seems the problem occur when a thread exec two consecutive times.
当线程连续两次执行时,似乎会出现问题。
The swap lock logic: 交换锁逻辑:
Every thread make use of a local variable and a shared variable. 每个线程都使用局部变量和共享变量。 A thread at first lock its local variable (eg assume 1 value).
线程首先锁定其局部变量(例如,假定值为1)。 When a thread local variable is unlocked (eg assume 0 value) it can execute the critical section, if the thread local variable is locked (eg assume 1 value) the thread is in a busy-waiting (the busy waiting tests the local variable unlocking and calls the swap function)
当线程局部变量被解锁(例如,假设值为0)时,它可以执行关键部分,如果线程局部变量被锁定(例如,假设值为1),则线程处于繁忙等待状态 (繁忙等待测试了局部变量的解锁)并调用交换功能)
The swap function sets the local variable to the shared variable value and viceversa.The swap function has to be ATOMIC. swap函数将局部变量设置为共享变量值,反之亦然。swap函数必须为ATOMIC。
When a thread call swap, if the the "shared" variables is 0 (unlock) after swap we have that shared variable is 1 and the local to 0. So only that thread can access to the critical section no others. 当线程调用交换时,如果交换后“共享”变量为0(解锁),则共享变量为1, 局部变量为0。因此,只有该线程才能访问关键部分,而其他线程不能访问。
At the end (no more critical section) the thread unlock the shared variable. 最后(不再需要关键部分),线程将共享变量解锁。
Main 主要
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();
}
}
Thread Class (The logic of this type of mutex is emphasized) 线程类 (强调这种互斥锁的逻辑)
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);
}
}
}
Swap function 交换功能
class Synch{
public static synchronized void SWAP(LockVar shared, LockVar local){
int temp = shared.getVar();
shared.setVar(local.getVar());
local.setVar(temp);
}
...
}
Shared var Class 共享变量类
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;
}
}
Imagine this scenario: 想象一下这种情况:
shared.setVar(local.getVar());
shared.setVar(local.getVar());
(now shared_var == 1) and local.setVar(temp);
local.setVar(temp);
(remember temp is 1 from step 2). The deadlock has been produced: shared_var is 1 and no thread is in the critical section. 产生了死锁:shared_var为1,并且临界区中没有线程。 This is because SWAP is not atomic (the monitor can move away from a thread executing a synchronized method, it will just not allow other threads to enter such method nor others method synchronized on the same lock (the class in the case of a static method, the instance of the object in the case of a non-static method)).
这是因为SWAP不是原子的(监视器可以从执行同步方法的线程中移开,它只会不允许其他线程进入该方法,也不允许其他方法在同一锁上同步(对于静态方法而言,该类为此类) ,如果是非静态方法,则为对象的实例))。
In order to fix this you should not allow shared to change while SWAP is executing, by finding a way of making it atomic. 为了解决此问题,您不应该允许SWAP执行时更改共享,方法是使其成为原子的。 A possibility would be to get rid of local and use compareAndSet on an AtomicBoolean which would play the role of shared_var at the moment.
一种可能是摆脱局部,并在AtomicBoolean上使用compareAndSet ,该AtomicBoolean目前将扮演shared_var的角色。
Atomic types guarantee atomicity and volatility (see documentation ). 原子类型保证原子性和挥发性(请参阅文档 )。 This way, every thread should get a reference (excuse my loose nomenclature) to the AtomicBoolean used for signaling and use compareAndSet to atomically update the value of the variable in a way that is visible immediately to the other threads:
这样,每个线程都应该获取用于信号发送的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.