I am learning multithreading
in class, so please no implemented solutions; improvement suggestions are appreciated though.
A 10,000 ft overview: main accepts 3 parameters (threads, resources, and runtime length). Each thread waits a random time, then decides to access the shared resources/critical section for a random time, upon completion relinquishing the resource. Repeat for provided runtime length, then exit all threads.
Based on the problem of users at a gocart track, taking turns riding and wandering around between rides.
I've created a deadlock, but I cannot find how that could be.
Sleeper just assigns the thread to wait for a time.
Rider 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.");}
}
}
The Coordinator class is where the meat is:
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);
}
}
Here is the console output for a deadlocked 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
答案 0 :(得分:3)
这是一个死锁场景:
Semaphore
cars
个令牌
getInLine
并等待cars#acquire
因为getInLine
是synchronized
而X具有锁定,所以N个线程中的任何一个都无法返回令牌。这是因为returnCar
方法也是synchronized
实现目标的更好方法是将carLine#removeFirst
和carLine#add
置于自己的synchronized
方法中,并从其他两种方法中移除synchronized
:< / p>
public synchronized int removeCar(){
return carLine.removeFirst();
}
public synchronized void addCar(int car){
carLine.add(car);
}
这也消除了对mutex
对象的需求。您改为使用Coordinator
对象本身作为互斥锁。这也意味着等待信号量上的acquire
不会阻止你返回它的标记