synchronized鎖住的是代碼仍是對象

不一樣的對象

public class Sync {
    public synchronized void test() {
        System.out.println("test start");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("test end");
    }
}

#html

public class MyThread extends Thread{
    public void run() {
        Sync sync = new Sync();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread();
            thread.start();
        }
    }
}

執行結果程序員

test start
test start
test start
test end
test end
test end  

現象swift

在MyThread中,每次都new一個新的Sync對象,能夠看到代碼塊test雖然被加了synchonized可是仍是並行執行的,初步結論:鎖住的不是代碼塊安全

同一個對象

public class MyThread2 extends Thread{
    public Sync sync;
    MyThread2(Sync sync) {
        this.sync = sync;
    }

    public void run() {
        System.out.println("hi....");
        sync.test();
    }

    public static void main(String[] args) {
        Sync sync = new Sync();
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread2(sync);
            thread.start();
        }
    }

執行結果bash

hi....
test start
hi....
hi....
test end
test start
test end
test start
test end  

現象併發

能夠看到當他們共用一個對象的時候,synchonized起了做用,這塊代碼是串行執行的性能

結論

鎖住的是對象this

如何在多對象的時候任然鎖住代碼?

解決也很簡單,只要鎖住同一個對象就好了。例如:synchronized後的括號中鎖同一個固定對象,這樣就好了。spa

這樣是沒問題,可是,比較多的作法是讓synchronized鎖這個類對應的Class對象。.net

public class Sync2 {
    public void test() {
        synchronized (Sync2.class) {
            System.out.println("test start");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("test end");
        }
    }
}

#

public class MyThread3 extends Thread{
    public void run() {
        Sync2 sync = new Sync2();
        sync.test();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; ++i) {
            Thread thread = new MyThread3();
            thread.start();
        }
    }
}

執行結果

test start
test end
test start
test end
test start
test end

synchronized的兩大不足

  • 因爲咱們沒辦法設置synchronized關鍵字在獲取鎖的時候等待時間,因此synchronized可能會致使線程爲了加鎖而無限期地處於阻塞狀態
  • 使用synchronized關鍵字等同於使用了互斥鎖,即其餘線程都沒法得到鎖對象的訪問權。這種策略對於讀多寫少的應用而言是很不利的,由於即便多個讀者看似能夠併發運行,但他們實際上仍是串行的,並將最終致使併發性能的降低。 

雖然synchronized已經做爲一個關鍵字被固化在Java語言中了,但它只提供了一種至關保守的線程安全策略,且該策略開放給程序員的控制能力極弱

參考

synchonized控制對象仍是代碼段

synchronized的兩大不足

相關文章
相關標籤/搜索