繁体   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