我的程序需要从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();
}
}
答案 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();
}
}