java.lang.IllegalMonitorStateException 在 Monitor class 的用餐哲学家中
java.lang.IllegalMonitorStateException in Monitor class of dining philosophers
我是监视器和条件变量的新手。我在监视器中使用锁和条件变量。
public class Monitor
{
private final int piNumberOfPhilosophers;
private PhilosopherCard[] self;
private Integer[] names;
private int invited = 0;
static Lock lock = new ReentrantLock();
private Condition[] status; // = lock.newCondition();
private String[] state;
/**
* Constructor
*/
public Monitor(int piNumberOfPhilosophers)
{ this.piNumberOfPhilosophers = piNumberOfPhilosophers;
self = new PhilosopherCard[this.piNumberOfPhilosophers];
names = new Integer[this.piNumberOfPhilosophers];
status = new Condition [this.piNumberOfPhilosophers];
state = new String [this.piNumberOfPhilosophers];
//Arrays.asList(state).indexOf(4);
}
public void invitePhilosopher (int id){
names[invited] = id;
System.out.println(invited);
PhilosopherCard philosopher = new PhilosopherCard("thinking");
self[invited] = philosopher;
status[invited] =lock.newCondition();
state[invited] = "thinking";
invited++;
}
/**
* check other philosophers (<_<) - > (0_o) -> (>_>)
*/
private void test (int index){
lock.lock();
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
if((state[left]!="eating")&(state[right]!="eating")){
state[index]="eating";
status[index].signal();
}
lock.unlock();
}
public void pickUp(final int piTID) throws InterruptedException
{
int index = Arrays.asList(names).indexOf(piTID);
state[index]="hungry";
test(index);
if(!state[index].equals("eating")){
status[index].wait();
}
}
/**
* When a given philosopher's done eating, they put the chopstiks/forks down
* and let others know they are available.
*/
public void putDown(final int piTID)
{
int index = Arrays.asList(names).indexOf(piTID);
self[index].setState("thinking");
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
test(left);
test(right);
// ...
}
}
在 putdown 中我们可以通过 self[index].signal 来唤醒显示器。但这并不重要。并且,当我们在条件变量上使用等待时,在 pickup 方法中发生监视器异常。为什么?因为他们都用一把锁?
所有踪迹
Exception in thread "Thread-1" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at Monitor.pickUp(Monitor.java:75)
at Philosopher.run(Philosopher.java:95)
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at Monitor.pickUp(Monitor.java:75)
at Philosopher.run(Philosopher.java:95)
我更新了代码并删除了额外的 class,所以一切都合而为一 class,也许现在更清楚错误在哪里了
你有很多地方做错了。
- 您在
this
上处于 synchronizing
,但未锁定 PhilosopherCard.lock
。通过锁定,我的意思是 PhilosopherCard.lock.lock();
- 您正在使用
wait
而不是 await
。
更新以获取更多信息
如果您查看您的这段代码并删除 synchronized
,代码将不会失败。
private void test (int index){
PhilosopherCard.lock.lock();
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
if((state[left]!="eating")&(state[right]!="eating")){
state[index]="eating";
status[index].signal();;
}
PhilosopherCard.lock.unlock();
}
你 signal
它类似于 await
,但是没有同步为什么它不会抛出 IMSE?那是因为你持有
PhilosopherCard.lock
锁定。如果您删除了那两个锁,您将获得一个 IMSE。
您 运行 关注 pickUp
中的那个问题。我会一起从方法中删除 synchronized
。为什么?因为你在混合同步。如果您想与 synchronized
同步,那很好,但是如果您要与 java.util.concurrent.Lock
同步,则不能使用 synchronized
.
synchronized
关键字可以让您在对象上使用 wait
、notify
和 notifyAll
。
j.u.c.Lock
和 j.u.c.Condition
允许您使用 await
、signal
、signalAll
。所以我的建议是只使用 Lock
/Condition
或 synchronized
。两者都不是。
我是监视器和条件变量的新手。我在监视器中使用锁和条件变量。
public class Monitor
{
private final int piNumberOfPhilosophers;
private PhilosopherCard[] self;
private Integer[] names;
private int invited = 0;
static Lock lock = new ReentrantLock();
private Condition[] status; // = lock.newCondition();
private String[] state;
/**
* Constructor
*/
public Monitor(int piNumberOfPhilosophers)
{ this.piNumberOfPhilosophers = piNumberOfPhilosophers;
self = new PhilosopherCard[this.piNumberOfPhilosophers];
names = new Integer[this.piNumberOfPhilosophers];
status = new Condition [this.piNumberOfPhilosophers];
state = new String [this.piNumberOfPhilosophers];
//Arrays.asList(state).indexOf(4);
}
public void invitePhilosopher (int id){
names[invited] = id;
System.out.println(invited);
PhilosopherCard philosopher = new PhilosopherCard("thinking");
self[invited] = philosopher;
status[invited] =lock.newCondition();
state[invited] = "thinking";
invited++;
}
/**
* check other philosophers (<_<) - > (0_o) -> (>_>)
*/
private void test (int index){
lock.lock();
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
if((state[left]!="eating")&(state[right]!="eating")){
state[index]="eating";
status[index].signal();
}
lock.unlock();
}
public void pickUp(final int piTID) throws InterruptedException
{
int index = Arrays.asList(names).indexOf(piTID);
state[index]="hungry";
test(index);
if(!state[index].equals("eating")){
status[index].wait();
}
}
/**
* When a given philosopher's done eating, they put the chopstiks/forks down
* and let others know they are available.
*/
public void putDown(final int piTID)
{
int index = Arrays.asList(names).indexOf(piTID);
self[index].setState("thinking");
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
test(left);
test(right);
// ...
}
}
在 putdown 中我们可以通过 self[index].signal 来唤醒显示器。但这并不重要。并且,当我们在条件变量上使用等待时,在 pickup 方法中发生监视器异常。为什么?因为他们都用一把锁? 所有踪迹
Exception in thread "Thread-1" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at Monitor.pickUp(Monitor.java:75)
at Philosopher.run(Philosopher.java:95)
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at Monitor.pickUp(Monitor.java:75)
at Philosopher.run(Philosopher.java:95)
我更新了代码并删除了额外的 class,所以一切都合而为一 class,也许现在更清楚错误在哪里了
你有很多地方做错了。
- 您在
this
上处于synchronizing
,但未锁定PhilosopherCard.lock
。通过锁定,我的意思是PhilosopherCard.lock.lock();
- 您正在使用
wait
而不是await
。
更新以获取更多信息
如果您查看您的这段代码并删除 synchronized
,代码将不会失败。
private void test (int index){
PhilosopherCard.lock.lock();
int left = index-1;
int right = index +1;
if(index==0){
left=piNumberOfPhilosophers-1;
}
if(index == piNumberOfPhilosophers-1){
right = 0;
}
if((state[left]!="eating")&(state[right]!="eating")){
state[index]="eating";
status[index].signal();;
}
PhilosopherCard.lock.unlock();
}
你 signal
它类似于 await
,但是没有同步为什么它不会抛出 IMSE?那是因为你持有
PhilosopherCard.lock
锁定。如果您删除了那两个锁,您将获得一个 IMSE。
您 运行 关注 pickUp
中的那个问题。我会一起从方法中删除 synchronized
。为什么?因为你在混合同步。如果您想与 synchronized
同步,那很好,但是如果您要与 java.util.concurrent.Lock
同步,则不能使用 synchronized
.
synchronized
关键字可以让您在对象上使用 wait
、notify
和 notifyAll
。
j.u.c.Lock
和 j.u.c.Condition
允许您使用 await
、signal
、signalAll
。所以我的建议是只使用 Lock
/Condition
或 synchronized
。两者都不是。