我是监控器和条件变量的新手。我在监视器中使用锁定和条件变量。
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);
// ...
}
}
在镇压中,我们可以自我[索引]。信号唤醒监视器。但这并没有那么重要。并且,在拾取方法中,当我们使用等待条件变量时,监控器会发生异常。为什么?因为他们都用一把锁?所有跟踪
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)
我更新了代码并删除了额外的类,所以所有这些都在一个类中,也许现在更清楚了
- 您在
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
。不是两者都有。