java中的锁和并发

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)

Hol*_*ger 5

您正试图在此循环中获取锁定: while(!maxChopstick.lock.tryLock()) …

这个循环在tryLock返回时结束true,暗示你有锁.但是你lock在循环之后另外调用因此已经锁定了两次.因此,单个unlock调用不会释放锁定.

但是您的代码也包含其他问题.您正在Philosopher根据棒号更换左侧和右侧的棒,这是没有意义的,因为该main方法已经为圆桌正确提供棒实例.对于最后一个人来说,当你将最后一个项目与第一个项目组合在一起时,将一个数字高于正确项目的左项目是正确的.交换它们然后打破最初正确的.

一旦你解决了这个问题,你将遇到与本答案中解释的相同的问题:如果所有的食客都先抓住左撇子,你可以达到所有食客都已经锁定左撇子并且无人可以进行的情况.

额外的编码风格赔率:你有一个ChineseStick类,但不是在grab那里提供操作,而是在Philosopher左右两侧的重复代码中实现它.如果ChineseStick只有一个pickUp()方法,Philosopher则只需要调用minChopstick.pickUp()maxChopstick.pickUp()分别实现两个pickUp…Chopstick()包含相同代码的方法.

而你正在混淆Locksynchronized.这是创建不可维护,令人困惑的代码的完美方式.