簡體   English   中英

Java中的鎖和並發

[英]Locks and concurrency in java

我是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();
    }
}



}

棍棒類:

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;
}

}

Main非常簡單:

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();
        }
    }

您正在嘗試在此循環中獲取鎖定: while(!maxChopstick.lock.tryLock()) …

tryLock返回true ,此循環結束,這表明您擁有鎖 但是您在循環之后因此又兩次調用了lock 因此,單個unlock調用不會釋放該鎖。

但是您的代碼也包含其他問題。 您正在根據搖桿號在Philosopher的構造函數中交換左右搖桿,這沒有意義,因為main方法已經為圓桌會議正確提供了搖桿實例。 當您環繞將最后一個項目與第一個項目組合在一起的數組時,最后一個人的左邊項目的編號比右邊項目的編號高是正確的。 交換它們會破壞最初正確的內容。

修復該問題后,您將遇到與該答案相同的問題:如果所有食用者都先抓住左棍,則可能會遇到所有食用者都鎖定左棍而沒人能繼續前進的情況。

其他編碼風格的問題:您有一個ChineseStick類,但是沒有在其中提供grab操作,而是在Philosopher中用左右搖桿的重復代碼實現了它。 如果ChineseStick有一個單一的pickUp()的方法,所述Philosopher只需要調用minChopstick.pickUp()maxChopstick.pickUp()分別而非實現兩個pickUp…Chopstick()包含相同的代碼的方法。

您正在混淆Locksynchronized 這是創建無法維護的,令人困惑的代碼的完美方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM