我正在类里面学习多线程
,所以请不要实现解决方案;不过,改进建议值得赞赏。
10,000 英尺概述:main 接受 3 个参数(线程、资源和运行时长度)。每个线程等待随机时间,然后决定随机访问共享资源/关键部分,完成后放弃资源。重复提供的运行时长度,然后退出所有线程。
针对卡丁车赛道上用户轮流骑行、骑行间隙闲逛的问题。
我已经造成了僵局,但我不知道这是怎么回事。
Sleeper只是分配线程等待一段时间。
骑手级别:
public void run() {
while (!coord.exit) {
System.out.format("Rider %d is gone walkabout%n", ID);
Sleeper.walkAround(ID);
System.out.format("Rider %d is in line%n", ID);
try {
carID = coord.getInLine();
System.out.format("Rider %d is riding car %d%n", ID, carID);
Sleeper.rideTime(ID);
coord.returnCar(carID);
} catch (InterruptedException ie) {System.out.println("Thread " + ID + " was interrupted.");}
}
}
Coordinator 类是关键所在:
public class Coordinator {
Rider[] riderArr;
Semaphore mutex = new Semaphore(1);
Semaphore cars;
LinkedList<Integer> carLine;
volatile static boolean exit = false;
public synchronized int getInLine() throws InterruptedException {
cars.acquire();
mutex.acquire();
int carid = carLine.removeFirst();
mutex.release();
return carid;
}
public synchronized void returnCar(int carID) throws InterruptedException {
mutex.acquire();
carLine.add(carID);
mutex.release();
cars.release();
}
public Coordinator(int cars, int riders) {
riderArr = new Rider[riders];
for (int i = 0; i < riders; i++) {
riderArr[i] = new Rider(this, i + 1);
}
carLine = new LinkedList<Integer>();
for (int i = 0; i < cars; i++) {
carLine.add(i + 1);
}
this.cars = new Semaphore(cars);
}
public static void main(String[] args) throws NumberFormatException, InterruptedException {
Coordinator coord = new Coordinator(Integer.parseInt(args[0]),
Integer.parseInt(args[1]));
for (int i = 0; i < Integer.parseInt(args[1]); i++) {
coord.riderArr[i].start();
}
Thread.sleep(1000 * Integer.parseInt(args[2]));
exit = true;
for (int i = 0; i < Integer.parseInt(args[1]); i++) {
coord.riderArr[i].join();
}
System.exit(0);
}
}
以下是死锁 session 的控制台输出:
Rider 2 is gone walkabout
Rider 2 is walking around for 4 seconds
Rider 1 is gone walkabout
Rider 1 is walking around for 1 seconds
Rider 1 is in line
Rider 1 is riding car 1
Rider 1 is riding for 3 seconds
Rider 2 is in line
最佳答案
这是一个死锁场景:
- N 个线程获取
cars
中的所有 N 个Semaphore
token - 线程 X 进入
getInLine
并等待cars#acquire
因为 getInLine
是同步
并且 X 拥有锁,所以 N 个线程中的任何一个都无法返回 token 。这是因为 returnCar
方法也是同步
实现目标的更好方法是将 carLine#removeFirst
和 carLine#add
放在它们自己的 synchronized
方法中,并且从其他两个方法中删除 synchronized
:
public synchronized int removeCar(){
return carLine.removeFirst();
}
public synchronized void addCar(int car){
carLine.add(car);
}
这也消除了您对互斥对象的需要。您可以使用 Coordinator 对象本身作为互斥锁。这也意味着等待信号量上的获取
不会阻止您返回其 token
关于java - 多线程简单死锁错误逃避检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36561725/