我是监视器和条件变量的新手。我在我的监视器中使用锁定和条件变量。
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中,我们可以自我[索引] .signal唤醒监视器。但它并不重要。并且,在拾取方法监视器异常发生时,我们在条件变量上使用wait时。为什么?因为他们都使用1锁? 全部跟踪
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)
我更新了代码并删除了额外的类,所以在一个类中,也许现在可以更明确的是哪个错误
答案 0 :(得分:2)
有很多事情你做错了。
synchronizing
上的this
并未锁定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
。不是两个。