![](/img/trans.png)
[英]Why Java throw java.lang.IllegalMonitorStateException when I invoke wait() in static way synchronized block?
[英]how can I change the lock I have aquired in a synchronized block, change it, and notifyAll() without getting java.lang.IllegalMonitorStateException?
我知道有人問過有關在同步塊中更改鎖的問題,但是在多線程套接字編程的客戶端中,我的類中有一個狀態枚舉,每當我想要更改它時,我都會得到鎖並進行更改。 同時,另一個線程正在等待(它也獲得了相同的鎖,並且在到達wait方法后放開了它)在更改程序線程進行更改並調用notifyAll()之后觀察更改。 現在,如果我想更改一個對象上的notifyAll()(我是指狀態枚舉),則會得到java.lang.IllegalMonitorStateException! 我考慮將另一個共享的最終對象用作我的鎖,但是通過這種方式,線程可能仍然能夠操縱狀態枚舉。 最好的方法是什么? 任何答案將不勝感激。 這是我的代碼的一部分:
這是轉換器線程:
synchronized (client.getStatus()) {
client.setStatus(ClientState.successfulRegistration);
client.getStatus().notifyAll()
}
這是等待的線程:
synchronized (client.getStatus()){
try {
client.getStatus().wait();
System.out.println("signMeIn notified");
ClientState result = client.getStatus();
System.out.println(result);
if(result.toString().equalsIgnoreCase("successfulSignIn") )
//do sth
} catch (InterruptedException e) {
e.printStackTrace();
}
這段代碼有錯誤:
synchronized (client.getStatus()) {
client.setStatus(ClientState.successfulRegistration);
client.getStatus().notifyAll()
}
只允許您對鎖定的對象進行notifyAll()。 但上方的一行用另一行替換了該對象。 更改鎖對象是一個非常糟糕的主意。 通常,您將使用“ this”或使用私有對象。
我建議以下解決方案:
public synchronized void setStatus(T status) {}
public synchronized T getStatus() {}
僅當您正在等待條件並想釋放鎖時,才需要使用wait()和notifyAll()方法。 這里是一個例子:
public synchronized void add(T element) {
while(full) {
wait();
}
data.add(element);
notifyAll();
}
public synchronized T remove() {
while(empty) {
wait();
}
T item = data.getAndremove();
notifyAll();
return item;
}
在此示例中,有許多隱藏的概念。 首先,您需要一個while循環來等待。 因為如果您等待並得到通知,您將返回准備運行隊列。 但是您不知道條件是否仍然成立,因此您必須重新檢查條件。 這就是為什么您使用while循環而不是if()的原因。
第二個概念通過“通知並恢復”已知。 可以通知()並保持鎖定狀態。 因此,您不必將notify()放在最后。
第三個概念是notify()和notifyAll()之間的區別。 第一個只喚醒一個線程。 如果數據為空,並且您喚醒了一個想要刪除某些內容的線程,那么將導致死鎖。 如果您將全部喚醒,則所有人將檢查條件是否滿足並嘗試繼續。
這是另一個匹配更多代碼的示例:
public synchronized void doSth() {
while(client.getStatus.equals("WAIT") {
wait();
}
System.out.println("Status isn't wait");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.