[英]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()
包含相同的代碼的方法。
您正在混淆Lock
和synchronized
。 這是創建無法維護的,令人困惑的代碼的完美方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.