分配多个锁定条件时会发生死锁

时间:2017-10-07 11:00:24

标签: 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();
    }
}

1 个答案:

答案 0 :(得分:0)

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

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