多线程简单死锁漏洞逃避检测
Multithreaded simple deadlock bug evading detection
我正在 class 学习 multithreading
,所以请不要实施解决方案;不过,我们还是很感激改进建议。
10,000 英尺概览:main 接受 3 个参数(线程、资源和运行时长度)。每个线程等待一个随机时间,然后决定随机访问共享 resources/critical 部分,完成后放弃资源。重复提供的运行时长度,然后退出所有线程。
基于卡丁车赛道用户轮流骑行和游走的问题
我创建了一个死锁,但我不知道那是怎么回事。
Sleeper只是分配线程等待一段时间。
骑手class:
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.");}
}
}
协调员class是肉所在:
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);
}
}
这是死锁会话的控制台输出:
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
个令牌
- 线程 X 进入
getInLine
并等待 cars#acquire
因为getInLine
是synchronized
并且X有锁,所以N个线程中的任何一个都没有办法return一个token。这是因为 returnCar
方法也是 synchronized
实现目标的更好方法是将 carLine#removeFirst
和 carLine#add
放在它们自己的 synchronized
方法中,并从其他两个方法中删除 synchronized
:
public synchronized int removeCar(){
return carLine.removeFirst();
}
public synchronized void addCar(int car){
carLine.add(car);
}
这也消除了您对 mutex
对象的需求。您改为使用 Coordinator
对象本身作为互斥体。这也意味着在信号量上等待 acquire
不会阻止您 returning 它的令牌
我正在 class 学习 multithreading
,所以请不要实施解决方案;不过,我们还是很感激改进建议。
10,000 英尺概览:main 接受 3 个参数(线程、资源和运行时长度)。每个线程等待一个随机时间,然后决定随机访问共享 resources/critical 部分,完成后放弃资源。重复提供的运行时长度,然后退出所有线程。
基于卡丁车赛道用户轮流骑行和游走的问题
我创建了一个死锁,但我不知道那是怎么回事。
Sleeper只是分配线程等待一段时间。
骑手class:
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.");}
}
}
协调员class是肉所在:
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);
}
}
这是死锁会话的控制台输出:
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 - 线程 X 进入
getInLine
并等待cars#acquire
Semaphore
个令牌
因为getInLine
是synchronized
并且X有锁,所以N个线程中的任何一个都没有办法return一个token。这是因为 returnCar
方法也是 synchronized
实现目标的更好方法是将 carLine#removeFirst
和 carLine#add
放在它们自己的 synchronized
方法中,并从其他两个方法中删除 synchronized
:
public synchronized int removeCar(){
return carLine.removeFirst();
}
public synchronized void addCar(int car){
carLine.add(car);
}
这也消除了您对 mutex
对象的需求。您改为使用 Coordinator
对象本身作为互斥体。这也意味着在信号量上等待 acquire
不会阻止您 returning 它的令牌