java中每個對象都有唯一的一個monitor,想擁有一個對象的monitor的話有以下三種方式:
1.執行該對象的同步方法
public synchronize a () {}
2.執行該對象的同步塊
synchronize(obj) {
}
3.執行某個類的靜態同步方法
public static synchronize b(){}
tips:擁有monitor的是線程
1.同時只能有一個線程可以獲取某個對象的monitor
2.一個線程通過調用某個對象的wait()方法釋放該對象的monitor並進入休眠狀態,
直到其他線程獲取了被該線程釋放的monitor並調用該對象的notify()或者notifyAll()後再次競爭獲取該對象的monitor
3.只有擁有該對象monitor的線程纔可以調用該對象的notify()和notifyAll()方法
如果沒有該對象monitor的線程調用了該對象的notify()或者notifyAll()方法將會拋出java.lang.IllegalMonitorStateException
測試代碼:
public class TestNotify implements Runnable {
private final Object obj = new Object();
@Override
public void run() {
synchronized (obj) {
notify();
//obj.notify();
}
}
public static void main(String[] args) {
//ShareVars shareVars = new ShareVars();
new Thread(new TestNotify ()).start();
}
}
當調用notify()時會拋出異常
狀態分析:
1.可以看到,此時線程執行的同步塊爲synchronized(obj),即只獲得了obj的monitir
2.notify()是調用TestNotify的方法,當前線程並未達到擁有TestNotify對象monitor的三個條件之一
3.所以拋出java.lang.IllegalMonitorStateException
wait()方法也和notify()一樣有相同的限制:
@Override
public void run() {
synchronized (obj) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
修改run方法爲上述代碼也會拋出java.lang.IllegalMonitorStateException