簡體   English   中英

方法同步,但由於非序列化的線程行為,代碼產生隨機結果

[英]Method synchronized , but code produces random result due to non-serialized thread behaviour

這是我的代碼:

public class ThreadDemo {

public static void main(String args[]) throws Exception {
    Printer[] printers = new Printer[5];
    printers[0] = new Printer("@base");
    printers[1] = new Printer("#try");
    printers[2] = new Printer("!test");
    printers[3] = new Printer("^hello");
    printers[4] = new Printer("*world");

    for (Printer x : printers) {
        x.start();
    }

    try {
        for (Printer y : printers) {
            y.join();
        }
    } catch (InterruptedException e) {
        System.out.println(e);
    }
  }
}

class Printer extends Thread {
public Printer(String name) {
    super(name);
}

public void run() {
    print();
}

public synchronized void print() {
    for (int i = 0; i < 10; i++) {
        System.out.print(getName().charAt(0));
        try {
            sleep(100);
        } catch (InterruptedException e) {
            System.out.println(e + " occured");
        }
    }
  }
}

它導致了

@^!#**@^!#*#@!^@*#^!#^!*@^*@!#@!#*^@#^!*!@^#*#@*^! 

我的期望是所有符號將根據首先啟動的線程序列化為@@@@@ ^^^^^。

調用sleep()會讓其他線程繼續進行直到當前線程的休眠時間,但我想不應該是同步方法的情況。

同步在這里不起作用。

該關鍵字確保您不能並行地在同一對象上調用相同的方法。

您正在不同的對象上調用它,因此即使沒有關鍵字,結果也會相同!

(我寧願假設您看到的結果實際上是由於在這里使用println()引起的。這是一個“非常慢”的操作,當超線程快速完成所有其他工作時,會引入“事實上的”同步。我試圖找到一些關於它的其他信息,但這可能需要更多時間)

您的代碼或我的問題會說您的期望是方法print在對象級別同步,並且您正在創建新的線程對象,啟動線程並調用此方法。

因此,在這種情況下,每個方法在每個單獨的線程對象上同步。 為了實現您期望的行為,我們可以使print方法保持靜態並查看行為更改。 您將獲得預期的結果,因為那時,方法print在一個Printer類鎖實例上同步。 因此,即使不同的線程實例正在調用此方法,因為對於類只有一個鎖,線程執行依次發生。

public static synchronized void print() {
    for (int i = 0; i < 10; i++) {
        System.out.print(Thread.currentThread().getName().charAt(0));
        try {
            sleep(100);
        } catch (InterruptedException e) {
            System.out.println(e + " occured");
        }
    }

}

@SolomonSlow - 所以必須糾正為'同步方法'可以同時在同一個對象上調用嗎?

關於同步實例方法,您只需要知道一件事。 你需要知道這......

synchronized void Foobar() { ... }

...只是編寫同步塊的快捷方式。

void Foobar() {
    synchronized (this) {
        ...
    }
}

這兩個方法聲明都完全相同 因此,您知道或了解同步塊行為的所有內容也可以應用於同步方法。

關於synchronized塊的最重要的事情是,“不能同時在同一個對象上同步兩個線程。” 如果您了解這一點,並且如果您知道同步方法只是同步塊的快捷方式,那么您可以回答自己的問題。

暫無
暫無

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

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