線程安全(隱式鎖synchronized和顯式鎖Lock及其實現類JUC.locks包)

1. Java內存模型(JMM)

Java作爲平臺無關性語言,它定義了一個統一的內存管理模型JMM(Java Memory Model),JMM屏蔽了操作系統底層內存管理細節,JMM規定了JVM有主內存(Main Memory)和工作內存(Working Memory),主內存就是平時所說的Java堆內存,存放程序中所有的類實例(對象)等,是多個線程共享的,而工作內存存放的是從主內存中拷貝過來的變量以及訪問方法所取得的局部變量,是每個線程私有的(其他線程不能訪問),每個線程對變量的操作都是先從主內存將其拷貝到工作內存再對其進行操作的方式進行多個線程之間不能相互傳遞數據進行通信,只能通過共享變量來進行通信

有關JMM的更多內容:Java內存模型

由於多個線程之間是不能互相傳遞數據通信的,它們之間的溝通只能通過共享變量的方式來進行。Java內存模型(JMM)規定了JVM有主內存,主內存是多個線程共享的。當new一個對象(實例)的時候,也是被分配在主內存中,每個線程都有自己的工作內存,工作內存存儲了主存的某些對象的副本(線程的工作內存大小是有限制的)。當線程操作某個對象時,執行順序如下:

  • 從主內存複製變量到當前工作內存(read、load)
  • 執行代碼,改變共享變量值(use、assign)
  • 用工作內存數據刷新主存相關內容(store、write)

2. 線程安全與線程不安全

線程不安全:多個線程對同一個對象中的同一個實例變量進行操作時會出現值被更改、值不同步的情況,影響程序的執行流程(出現髒讀)。

“線程不安全”的問題存在於“實例變量”中,如果是方法內部的私有變量,則不存在非線程安全問題。即在方法內部聲明一個變量時,是不存在“線程不安全”問題的。因爲方法內部的變量是私有的。

3. 隱式鎖(synchronized)

synchronized是Java語言的關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多隻有一個線程執行該段代碼。相當於加了一把鎖,但是不需要加鎖和解鎖的操作,所以稱它爲隱式鎖。

synchronized取得的鎖都是對象鎖(修飾普通方法)或類鎖(修飾static方法),而不是把一段代碼或方法當做鎖。調用用關鍵字synchronized聲明的方法一定是排隊運行的。它用於解決多線程之間的數據共享問題,具有同步功能,是一種互斥鎖,鎖的是類的單個對象或所有對象。

(1)synchronized修飾代碼塊:

public void methodA(){
    synchronized (this){
        System.out.println(Thread.currentThread().getName());
    }
}

(2)synchronized修飾方法:

public synchronized void methodB(){
    System.out.println(Thread.currentThread().getName());
}

關於synchronized的文章:synchronized

4. 顯式鎖Lock和ReadWriteLock

Lock是一個接口,提供了常用的鎖操作,加鎖和解鎖的方法都是顯式的。包路徑是java.util.concurrent.locks.lock

Lock的核心方法是

  • void lock():獲取鎖。如果鎖不可用,將禁用當前線程,並在獲得鎖之前,該線程將一直處於休眠狀態。
  • unlock():釋放鎖。
  • tryLock()
  • newCondition():用來返回與此Lock對象一起使用的Condition實例。

Lock的實現類有

  • ReentrantLock
  • ReentrantReadWriteLock.ReadLock
  • ReentrantReadWriteLock.WriteLock

Lock與synchronized的比較:

  • Lock使用起來比較靈活;
  • Lock必須手動的開啓鎖和釋放鎖,而synchronized不需要手動釋放鎖和開啓鎖;

4.1 ReentrantLock

ReentrantLock是Lock的實現類之一,是一個同步的互斥器,它具有擴展的能力。

缺點:可能會忘記釋放鎖。(必須在finally塊中保證每次用完都釋放鎖)

詳細內容:ReentrantLock(Lock)

4.2 ReadWriteLock和ReentrantReadWriteLock

ReadWriteLock是一個接口,它實現了讀寫鎖,同一時刻多個讀線程可並行訪問,而只能允許一個寫線程訪問。ReentrantReadWriteLock是它的一個實現類,讀寫鎖可在一定程度上提高併發讀寫的效率。

詳細內容:ReadWriteLock和ReentrantReadWriteLock(讀寫鎖)

4.3 StampedLock

StampedLock可以更好的實現悲觀鎖和樂觀鎖的邏輯。它使用三種模式來控制讀、寫訪問。StampedLock的狀態包含了版本和模式。鎖獲取方法根據鎖的狀態返回一個表示和控制訪問的標誌(stamp)

後期補。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章