簡體   English   中英

無法理解Java中的同步塊

[英]Can't understand Synchronized block in java

我試圖研究Java中的線程同步,后來才知道同步塊。 我可能會問一個愚蠢的問題,因為我對線程同步了解不多,但是在此程序中,我無法理解該塊的行為。

class Table {
    void printTable(int n) { //method not synchronized
        for(int i=1; i<=10; i++) {
            System.out.println(n + " * " + i + " = " + n*i);
            try {
                Thread.sleep(500);
            } catch(Exception e) {
                System.out.println(e);
            }
        }
        System.out.println("Table of " + n + " is completed.");
    }
}

class MyThread extends Thread {
    Table t;
    int num;

    MyThread(Table t, int num) {
        this.t = t;
        this.num = num;
    }

    public void run() {
      synchronized(t) {
        t.printTable(num);
      }
    }
}

class TestSynchronization {
    public static void main(String[] args) {
        Table obj = new Table(); //only one object
        MyThread t1;
        MyThread t2;

        t1 = new MyThread(obj, 10);
        t2 = new MyThread(obj, 17);

        t1.start();
        t2.start();
    }
}

它的輸出是這樣的:

10 * 1 = 10
10 * 2 = 20
10 * 3 = 30
10 * 4 = 40
10 * 5 = 50
Table of 10 is completed.
17 * 1 = 17
17 * 2 = 34
17 * 3 = 51
17 * 4 = 68
17 * 5 = 85
Table of 17 is completed.

這似乎是正確的,但是當我嘗試通過從run方法中刪除同步塊並將其應用到void mainobj對象中來執行相同操作時,它會顯示不同的輸出。

class Table {
    void printTable(int n) { //method not synchronized
        for(int i=1; i<=5; i++) {
            System.out.println(n + " * " + i + " = " + n*i);
            try {
                Thread.sleep(500);
            } catch(Exception e) {
                System.out.println(e);
            }
        }
        System.out.println("Table of " + n + " is completed.");
    }
}

class MyThread extends Thread {
    Table t;
    int num;

    MyThread(Table t, int num) {
        this.t = t;
        this.num = num;
    }

    public void run() {
        t.printTable(num);
    }
}

class TestSynchronization {
    public static void main(String[] args) {
        Table obj = new Table(); //only one object
        MyThread t1;
        MyThread t2;

        synchronized(obj) {
        t1 = new MyThread(obj, 10);
        t2 = new MyThread(obj, 17);
        }

        t1.start();
        t2.start();
    }
}

輸出:

10 * 1 = 10
17 * 1 = 17
10 * 2 = 20
17 * 2 = 34
17 * 3 = 51
10 * 3 = 30
17 * 4 = 68
10 * 4 = 40
10 * 5 = 50
17 * 5 = 85
Table of 17 is completed.
Table of 10 is completed.

為什么在第二種情況下不起作用,請向我解釋。

還建議我在可能的情況下通過在void main使用同步塊來獲得相同輸出的方式。

不同之處在於獲取Table類對象的lock 位置時間

在第一個示例中,對Table對象的鎖定是在MyThread類的實例內部獲取的。 假設MyThread類的第一個實例獲取表對象鎖,則MyThread類的其他實例將無法獲取對表對象的鎖,直到第一個實例又將其釋放,即線程級同步

在第二個示例中,對對象的鎖定是由驅動程序獲取的,因此從技術上講,在此級別上沒有並發問題,因為該鎖定與驅動程序而不是與各個線程無關,這實際上是一種過程。級同步

同步塊是一個房間,並且已將同步塊應用於對象。 在第一個示例中,將同步塊應用於類表對象。 當任何線程嘗試訪問該方法時,它必須首先像進入房間一樣進入同步塊,而當諸如t1的線程進入該塊時,房間將被鎖定,直到t1完成執行,然后才能執行該操作。線程t2進入房間。

如果沒有同步塊,線程之間會相互交織,因此輸出會有所不同,如果t1在t2開始之前完成執行,則有時輸出是正確的,但是在大型應用程序中,它將干擾並會導致不同的輸出,如您所述在第二個示例中。 因此,為了防止此類交織,我們使用同步塊或thrsecad安全類,例如,阻塞隊列等。

同步塊

   synchronized(mutex){
     x =y;
     y=z;
   }

互斥鎖=互斥。 那些可以共享同一對象(即互斥體)的線程列表中的一個線程可以執行的塊

首先,互斥對象是對象,而Java中的每個對象都有一個稱為鎖的信號量。

如果線程A和B與c共享了互斥鎖,則線程A在進入同步塊之前必須獲取鎖,即在進入之前獲取

釋放發生在獲取之前,即,如果一個線程已經獲取了鎖,則另一個線程必須等待直到第一個線程不釋放鎖。

同步塊的另一個功能是,獲取鎖的每個線程都需要直接從主內存中讀取塊中涉及的所有變量,而不是從緩存中讀取停頓值,並且必須在更改后將這些變量寫入主內存,然后再離開該塊。

即變量值更新發生在獲取之后,而內存寫入發生在釋放之前,因此下一個線程將具有最新值要處理。

暫無
暫無

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

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