簡體   English   中英

線程並發 - 同步和鎖定。

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM