Rot*_*m B 2 java multithreading
我是java并发新手并使用锁.我试图解决用餐问题,我没有死锁,但只有一个线程获得实际的运行时间.谁能告诉我我做错了什么?
class Philosopher implements Runnable {
private Random numGenerator = new Random();
private int id;
private ChineseStick minChopstick;
private ChineseStick maxChopstick;
public Philosopher (int id, ChineseStick leftChopstick, ChineseStick rightChopstick) {
this.id = id;
if(leftChopstick.getNumber() > rightChopstick.getNumber()){
this.minChopstick = rightChopstick;
this.maxChopstick = leftChopstick;
}
else{
this.minChopstick = leftChopstick;
this.maxChopstick = rightChopstick;
}
}
/**
* Repeatedly think, pick up chopsticks, eat and put down chopsticks
*/
public void run() {
try {
while (true) {
pickUpLeftChopstick();
pickUpRightChopstick();
eat();
putDownChopsticks();
think();
}
} catch (InterruptedException e) {
System.out.println("Philosopher " + id + " was interrupted.\n");
}
catch(Exception e){
System.out.println("Philosopher " + id + " raised exceptions.\n");
}
}
/**
* Lets a random amount of time pass to model thinking.
* @throws InterruptedException
*/
private void think() throws InterruptedException {
System.out.println("Philosopher " + id + " is thinking.\n");
System.out.flush();
Thread.sleep (numGenerator.nextInt(10));
}
/**
* Locks the left chopstick to signify that this philosopher is holding it
* @throws InterruptedException
*/
private void pickUpLeftChopstick() throws InterruptedException {
while(!minChopstick.lock.tryLock()){
synchronized(minChopstick.lock){
minChopstick.lock.wait();
}
}
minChopstick.lock.lock();
System.out.println("Philosopher " + id + " is holding " + this.minChopstick.getNumber() + " chopstick.\n");
System.out.flush();
}
/**
* Locks the right chopstick to signify that this philosopher is holding it
* @throws InterruptedException
*/
private void pickUpRightChopstick() throws InterruptedException {
while(!maxChopstick.lock.tryLock()){
synchronized(maxChopstick.lock){
maxChopstick.lock.wait();
}
}
maxChopstick.lock.lock();
System.out.println("Philosopher " + id + " is holding " + this.maxChopstick.getNumber() + " chopstick.\n");
System.out.flush();
}
/**
* Lets a random amount of time pass to model eating.
* @throws InterruptedException
*/
private void eat() throws InterruptedException {
System.out.println("Philosopher " + id + " is eating.\n");
System.out.flush();
Thread.sleep (numGenerator.nextInt(10));
}
/**
* Releases the locks on both chopsticks to model putting them down so the
* other philosophers can use them.
*/
private void putDownChopsticks() {
minChopstick.lock.unlock();
synchronized(minChopstick.lock){
minChopstick.lock.notifyAll();
}
maxChopstick.lock.unlock();
synchronized(maxChopstick.lock){
maxChopstick.lock.notifyAll();
}
}
}
Run Code Online (Sandbox Code Playgroud)
棒类:
public class ChineseStick {
public ChineseStick(int number){
this.lock = new ReentrantLock();
this.number = number;
}
public Lock lock;
private int number;
public int getNumber(){
return this.number;
}
}
Run Code Online (Sandbox Code Playgroud)
主要很简单:
public static void main (String[] args) {
// Model each chopstick with a lock
//Lock[] chopsticks = new ReentrantLock[NUM_PHILOSOPHERS];
ChineseStick[] sticks = new ChineseStick[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sticks[i] = new ChineseStick(i);
}
// Create the philosophers and start each running in its own thread.
Philosopher[] philosophers = new Philosopher[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
philosophers[i] = new Philosopher(i, sticks[i], sticks[(i+1)%NUM_PHILOSOPHERS]);
new Thread(philosophers[i]).start();
}
}
Run Code Online (Sandbox Code Playgroud)
您正试图在此循环中获取锁定: while(!maxChopstick.lock.tryLock()) …
这个循环在tryLock返回时结束true,暗示你有锁.但是你lock在循环之后另外调用因此已经锁定了两次.因此,单个unlock调用不会释放锁定.
但是您的代码也包含其他问题.您正在Philosopher根据棒号更换左侧和右侧的棒,这是没有意义的,因为该main方法已经为圆桌正确提供棒实例.对于最后一个人来说,当你将最后一个项目与第一个项目组合在一起时,将一个数字高于正确项目的左项目是正确的.交换它们然后打破最初正确的.
一旦你解决了这个问题,你将遇到与本答案中解释的相同的问题:如果所有的食客都先抓住左撇子,你可以达到所有食客都已经锁定左撇子并且无人可以进行的情况.
额外的编码风格赔率:你有一个ChineseStick类,但不是在grab那里提供操作,而是在Philosopher左右两侧的重复代码中实现它.如果ChineseStick只有一个pickUp()方法,Philosopher则只需要调用minChopstick.pickUp()和maxChopstick.pickUp()分别实现两个pickUp…Chopstick()包含相同代码的方法.
而你正在混淆Lock和synchronized.这是创建不可维护,令人困惑的代码的完美方式.