[英]Thread concurrency - synchronisation and locks.
import java.util.*;
import java.io.*;
import java.util.regex.*;
class ZiggyTest2 extends Thread{
String sa;
public ZiggyTest2(String sa){
this.sa = sa;
}
public void run(){
synchronized(sa){
while(!sa.equals("Done")){
try{
sa.wait();
}catch(InterruptedException is){System.out.println("IE Exception");}
}
}
System.out.println(sa);
}
}
class Test{
private static String sa = new String("Not Done");
public static void main(String[] args){
Thread t1 = new ZiggyTest2(sa);
t1.start();
synchronized(sa){
sa = new String("Done");
sa.notify();
}
}
}
當我運行上述程序時,我得到以下異常:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at Test.main(ZiggyTest2.java:35)
幾個問題:
為什么IllegalMonitorStateException? 因為Test.sa被分配給一個新的String對象,所以我期望ZiggyTest2線程無限期地等待,因為sa.notify()將在與ZiggyTest2中使用的鎖不同的鎖上被調用。
在上面的示例中,在“sa”對象上調用wait()和notify()。 說自己調用notify()並使用對象即sa.wait()和sa.notify()調用notify()/ wait()有什么區別?
在Test類中,synchronized塊是否具有sa對象的鎖並且sa對象是靜態的,但在ZiggyTest2類中,synchronized塊使用相同的sa對象引用但使用非靜態引用是否重要? 鑒於一個是靜態的而另一個不是靜態的,它們是否仍然使用相同的鎖?
當你執行
sa = new String("Done");
不要用sa
更改String引用的內容。 您將新的String實例(新對象)分配給sa
。 字符串是不可變的。 改變它們的價值是不可能的。
這意味着您在sa上同步(第一個對象:“Not Done”),然后將新對象分配給sa(第二個對象:“Done”),並在第二個對象上調用notify。 由於您沒有同步第二個對象,但是在第一個對象上,您會收到IllegalMonitorException。 僅當您擁有對象的內部鎖定時,才允許在對象上調用通知。 這就是鎖定永遠是最終的原因。
調用notify()等同於調用this.notify()。 所以this.notify()
和sa.notify()
只是在兩個不同的對象上調用notify()
。 第一個將通知等待this
的線程,第二個將通知等待sa
的線程。
變量是靜態的事實並不重要。 鎖與對象相關聯,而不是與其引用相關聯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.