Java-物件及變數的併發訪問小結

振宇要低調發表於2018-10-24

1)多執行緒環境下,方法內的變數是執行緒安全的

2)多個執行緒同時處理一個例項,這個例項內的變數是不安全的

3)不同執行緒中注入同一個類的不同例項,例項中的變數是安全的

4)Synchronized獲取到的鎖是物件鎖,當多個執行緒訪問同一個物件時,哪個執行緒先執行帶Synchronized關鍵字的方法,哪個執行緒就持有該方法所屬物件的鎖,其他執行緒是等待狀態

5)呼叫關鍵字Synchronized宣告的方法一定是排隊執行的,另外,只有共享資源的訪問才需要同步化

6)一個物件內有多個Synchronized方法/塊時

  A)A執行緒先持有object物件的鎖,B執行緒可以以非同步的方式呼叫object物件的非Synchronized方法

  B)A執行緒先持有object物件的鎖,B執行緒如果此時呼叫object物件中的任一Synchronized方法,則需要等待A執行緒釋放鎖,也就是同步

7)例項中有兩個變數,有一個Synchronized宣告的方法,方法執行過程中,若一個變數賦值完成,一個變數未賦值完成,此時呼叫例項中非Synchronized方法去獲取例項中兩個變數的值,此時就會出現髒讀,解決的辦法是讀取的方法上也加入Synchronized宣告

8)Synchronized是物件鎖,A執行緒獲取到物件鎖時,可執行被Synchronized宣告的X方法,其他執行緒想要執行這個物件的任何被Synchronized宣告的方法都得等待A釋放,因為其他執行緒未獲取到鎖

9)Synchronized鎖重入,在使用Synchronized時,當一個執行緒得到物件鎖時,在此請求此物件的物件鎖可以再次得到該物件的鎖,一個Synchronized方法/塊內部,可以呼叫本類的其他Synchronized方法/塊(也就是說只要不釋放,能夠一直獲取本例項的鎖)

10)Synchronized不能繼承,舉個栗子,父類方法被Synchronized修飾,子類覆寫父類的該方法,但並不帶Synchronized修飾,就不會產生同步的效果

11)Synchronized程式碼塊,肯定比Synchronized方法效能要好一些,也就是說Synchronized後面大括號,包裹的程式碼越少越好。當一個執行緒在執行Synchronized程式碼塊時,其他執行緒可以執行這個程式碼塊外部的程式碼

12)Synchronized程式碼塊與Synchronized方法特性基本相同

13)任意物件都可以作為物件監視器,可以Synchronized(任意物件),優點:如果一個類中有很多個Synchronized方法,這時雖然能夠實現同步,但會受到阻塞,所以影響執行效率;但如果使用同步程式碼塊鎖非this物件,則Synchronized(非this)程式碼塊的程式與同步方法是非同步的,不與其他鎖this同步方法爭搶this鎖,可大大提高執行效率

  A)當多個執行緒同時執行Synchronized(X,非this)同步程式碼塊時呈同步效果

  B)當其他執行緒執行X物件中Synchronized同步方法時也呈同步效果

  C)當其他執行緒執行X物件方法裡面的Synchronized(this)時也呈同步效果

14)Synchronized可以用在static關鍵字之上,表示對當前類持鎖,class鎖。class鎖可以對類的所有物件例項起作用。也就是說,對於class A來說,即便多個執行緒中每個執行緒建立一個A的例項,只要他們呼叫的是A中static synchronized的方法(或者static方法中的synchronized程式碼塊),就得等著,就是同步

15)通常情況下,都不會將String作為鎖物件,因為String存在一個常量池,當兩個執行緒呼叫的String相等時,相當於是競爭同一個鎖;另外,當鎖住某個String變數時x,若同步方法內對x進行了更改,相當於鎖物件就變化了,其他再來競爭鎖就能競爭到,就起不到同步的效果了(需要注意的是,只要物件不變,即便物件的屬性發生變更,也是同步的,String是因為其池化導致的一系列不同)

16)當一個synchronized方法中出現死迴圈時(永遠都不會釋放鎖),其他呼叫改物件中synchronized方法的執行緒均會一直等下去,解決方法是儘量每個方法鎖不同的物件,而不是都鎖this

17)死鎖,一個方法,先鎖A,等一會再鎖B;另一個方法,先鎖B,等一會再鎖A;當兩個方法同時執行時,就出現死鎖了。

18)volatile的主要作用是使變數在多個執行緒間可見。原理是強制執行緒從公共堆疊中獲得變數的值,而不是從執行緒的私有堆疊中取值。(舉個栗子:當JVM設定為-server模式時,為了執行緒執行的效率,執行緒一直在私有堆疊中取值,這樣,在一個while(x)的迴圈中,就算外部將x設定為false,執行緒內也不會跟著改變,從而進入到死迴圈狀態,這是就需要用到volatile關鍵字了。volatile主要使用的場合是在多個執行緒中,可以感知例項變數被改變了,並且獲得最新的值使用)

19) volatile本質上解決的是私有堆疊與公共堆疊中的值不同步

20)volatile與synchronized的異同

  A)volatile是執行緒同步的輕量級實現,效能要比synchronized好;volatile只能修飾變數,而synchronized可以修飾方法或者程式碼塊,synchronized還有效能提升的空間

  B)使用volatile不會產生阻塞,而使用synchronized會產生阻塞

  C)volatile保證可見性,但不保證原子性;synchronized保證原子性,間接保證可見性(一個變數只能在同步中操作完成了,才能被其他執行緒操作,所以叫間接)

  D)volatile解決的是變數在多個執行緒之間的可見性,而synchronized解決的是多個執行緒訪問資源的同步性

21)synchronized可以保證在同一時刻,只有一個執行緒可以執行某一個方法或者某一程式碼塊,它包含兩個特性:互斥性和可見性。不進可以解決一個執行緒看到物件處於不一致狀態,還可以保證進入同步方法或者同步程式碼塊的每個執行緒,都看到由同一個鎖保護之前的所有的修改效果。

相關文章