java - 当指定多个条件锁定时会出现死锁

标签 java multithreading monitoring deadlock reentrantlock

我的程序要求从 10 向后打印到 1。每个数字从 一个线程。它使用带有多个条件对象的一把锁。但是 程序在运行时导致死锁。这是我的程序。

<小时/>

这个类工作正常

import java.util.concurrent.*;
import java.util.*;

public class Backward {
   public static void main(String[] args) {
      BackwardThread[] threads = new BackwardThread[10];
      MonitorArray monitorArray = new MonitorArray(10);
      for(int i = 0; i < 10; ++i) {
         threads[i] = new BackwardThread("thread" + i, i, monitorArray);
         threads[i].start();
      }
   }
}
<小时/>

这个类工作正常

import java.util.concurrent.*;
import java.util.*;

public class BackwardThread extends Thread {
   private int id;
   private MonitorArray monitorArray;

   public BackwardThread(String name, int id, MonitorArray monitorArray) {
       super(name);
       this.id = id;
       this.monitorArray = monitorArray;
   }

  public void run() {
      monitorArray.waitTurn(id);
      System.out.println("hello world thread id = " + id);
      monitorArray.signalDone(id);
  }
}
<小时/>

似乎所有线程都永远锁定并且条件[id].signal()不起作用。

import java.util.concurrent.locks.*;
import java.util.concurrent.locks.Condition;

public class MonitorArray {

    private Lock lockvar;
    private Condition[] conditions;
    private int turn;

    public MonitorArray(int num) {
        this.lockvar = new ReentrantLock();
        this.conditions = new Condition[num];
        turn = num;
        for (int i = 0; i < num; ++i) {
            conditions[i] = lockvar.newCondition();
        }
        // TODO: need to initialize new variable here
    }
    public void waitTurn(int id) {
        lockvar.lock();
        while (id != turn) {
            try {
                conditions[id].await();
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
        lockvar.unlock();
    }

    public void signalDone(int id) {
        lockvar.lock();
        // TODO: Need to modify new variable here to allow one of the threads
        // blocked on the while to continue
        turn--;
        if (id != 0) {
            conditions[id].signal();
        }

        lockvar.unlock();
    }
}

最佳答案

我已经找到了解决方案,我将在代码注释中给出我的解释

import java.util.concurrent.locks.*;
import java.util.concurrent.locks.Condition;

public class MonitorArray {

    private Lock lockvar;
    private Condition[] conditions;
    private int turn;

    public MonitorArray(int num) {
        this.lockvar = new ReentrantLock();
        this.conditions = new Condition[num];

        /*
        / the turn value should should be num-1(9) instead of num(10) 
        / because if turn = 10 so all threads will be in waiting section,
        / so there will be no thread to send the signal to wake up other threads
        */
        turn = num-1;
        for (int i = 0; i < num; ++i) {
            conditions[i] = lockvar.newCondition();
        }

    }
    public void waitTurn(int id) {
        lockvar.lock();
        while (id != turn) {
            try {
                conditions[id].await();
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
        lockvar.unlock();
    }

    public void signalDone(int id) {
        lockvar.lock();
        // TODO: Need to modify new variable here to allow one of the threads
        // blocked on the while to continue
        turn--;
        if (id != 0) {

        /* 
        / this should be conditions[turn].signal(), not conditions[id] 
        / because a thread cannot wake up themself,
        / when we use condition[turn] we are in thread 9 and we sent signal to wake up thread 8, 
        / and furthermore, turn is reduced value and wake up the next smaller thread.
        */
            conditions[turn].signal();
        }

        lockvar.unlock();
    }
}

关于java - 当指定多个条件锁定时会出现死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46619426/

相关文章:

java - 仅在访问同一对象的同一方法时才锁定线程

c - 与不同线程共享数据的最快方法?

hadoop - Ganglia 无法与 Apache HBase 通信

bash - 如何通过 TCP 匹配模式?

java - 无法在 Windows 7 上为 Eclipse 项目运行 vertx 模块

Java Stack显示方法,在Stack顶部显示一个 '0'?

java - 多线程会导致每个任务花费更长的时间吗?

amazon-web-services - 网络数据输出 - nmon/nload 与 AWS Cloudwatch 差异

java - 用户输入后剩余数组数的总和

java - UIAutomator 在 Linux 上构建时运行 0 个测试,但在其他平台上运行良好