【问题标题】:Java - Deadlock using SWAP function to solve mutual exclusionJava - 使用 SWAP 函数解决互斥的死锁
【发布时间】:2015-04-07 04:57:23
【问题描述】:

我想使用 Swap 功能解决互斥问题,但程序出现死锁,我不知道为什么。当一个线程连续执行两次时似乎会出现问题。

交换锁逻辑:

每个线程都使用一个 local 变量和一个 shared 变量。 一个线程首先锁定它的 local 变量(例如假设 1 个值)。 当线程 local 变量被解锁(例如假设 0 值)它可以执行临界区,如果线程 local 变量被锁定(例如假设 1 值)线程被在busy-waiting中(忙着等待测试局部变量解锁并调用swap函数)

swap 函数将 local 变量设置为 shared 变量值,反之亦然。swap 函数必须是 ATOMIC。

当一个线程调用swap时,如果“shared”变量在swap之后为0(解锁),那么shared变量为1,local为0。 所以只有那个线程可以访问临界区,其他线程不能访问。

在最后(不再是关键部分)线程解锁 shared 变量。

主要

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;
    }
}

【问题讨论】:

  • 预期结果是什么?你得到的实际结果是什么?请注意,您在每个循环结束时以非同步方式使用 setVar。
  • 对不起,我会编辑正确的代码..
  • 加速的结果是一个连续的线程执行,如果一个线程在临界区,没有其他线程可以执行它们的临界区。实际结果是死锁,代码适用于 3 - 4 个线程执行,然后发生死锁。 (共享变量不假定 0 值)
  • 是的,事实上在调试之后我注意到setVar(0)调用shared_var对象的“var”属性的值没有改变。
  • 我敢打赌,该变量在循环结束时被设置为 0,但很快被 SWAP 中间的另一个线程覆盖。我目前的环境还没有为Java开发设置,如果仍然没有解决,我今晚会试试看:)

标签: java synchronization deadlock swap mutual-exclusion


【解决方案1】:

想象一下这个场景:

  1. 第一个线程交换 local 和 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 执行时允许 shared 更改,方法是找到一种使其成为原子的方法。一种可能是摆脱本地并在 AtomicBoolean 上使用 compareAndSet,这将在此刻扮演 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);
    }
  }
}

【讨论】:

  • 非常感谢,您帮助我提高了对显示器的了解。所以这是一个解决方案: Thread Class ... ... ... Synch.SET(shared_var, 0); ... 同步类 ` class Synch{ public synchronized static void SET(LockVar shared, int value){ shared.setVar(value); } 公共同步静态无效交换(LockVar 共享,LockVar 本地){ int temp = shared.getVar(); shared.setVar(local.getVar()); local.setVar(temp); } `
猜你喜欢
  • 2015-10-26
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
相关资源
最近更新 更多