簡體   English   中英

為什么在此示例中使用同步(Java並發)是不正確的?

[英]Why this is not right by using synchronized (Java concurrency) in this example?

我有兩個如下的Java類...

(1)JavaClass SyncTest:它定義一個類(實現Runnable)並調用在SyncTestCalled類中定義的“同步”方法(名為“ call”)

(2)JavaClass SyncTestCalled:有一種同步方法。

------
    After calling from main(), I am thinking it should output something like:  
[Two]
[Three]
[One]

But, it outputs something like this (note the open bracket which is not paired in right locations) : 

[[[Two]
Three]
One]

代碼有什么問題? 請幫忙。 非常感謝!


    Here is the code of these two classes...


    public class SyncTest implements Runnable {    
        Thread t;   
        String name;
        SyncTestCalled syncTestCalled;    
        public SyncTest(String name) {
                t = new Thread(this, name);
                syncTestCalled = new SyncTestCalled();
                this.name = name;
                t.start();
        }    
        public void run() {             
                syncTestCalled.call(this.name);
        }       
        public static void main(String[] args) {
                SyncTest syncTest1 = new SyncTest("One");
                SyncTest syncTest2 = new SyncTest("Two");
                SyncTest syncTest3 = new SyncTest("Three");
        }   
      } // of class SyncTest
    public class SyncTestCalled {
        public SyncTestCalled() {
        // Do nothing
        }    
        synchronized public void call(String message) {
                System.out.print("[");
                try {
                     Thread.sleep(1000);
                     System.out.print(message);
                } catch (InterruptedException e) { 
                     e.printStackTrace();
                }
                System.out.println("]");
        }
    } // of class SyncTestCalled

當您將synchronized作為方法聲明的一部分使用時,Java會嘗試在調用該方法的對象上獲取監視器(鎖)。 所以像

synchronized public void call(String message) {
    ...
}

相當於

public void call(String message) {
    synchronized (this) {
        ...
    }
}

在您的代碼中,您將創建三個不同的SyncTestCalled對象,並將每個對象傳遞給不同的SyncTest實例。 換句話說,什么都不協調。 每次致電

syncTestCalled.call(this.name);

在另一個對象上同步,因此沒有一個線程需要等待其他線程。

這取決於線程調度程序首先到達的位置,因此您將獲得如下輸出

[[[Two]
Three]
One]

要么

[[[OneThree]
Two]
]

請注意, Thread.sleep(long)不會放棄該線程當前具有的任何監視器。

在任何給定時間,只有一個線程可以在給定實例上調用call()方法。 但是,您想要的是對System.out.print()方法的多次調用的原子性。 為此,您需要獲取對System.out的鎖定:

synchronized (System.out) {
  System.out.print('[');
  System.out.print(message);
  System.out.println(']');
}

由於PrintStream自身鎖定,因此可以防止其他線程交錯自己對print()的調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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