Java多執行緒synchronized關鍵字引出的多種鎖
一、synchronized機制
synchronized
關鍵字是JAVA中常用的同步功能,提供了簡單易用的鎖功能。
synchronized
有三種用法,分別為:
- 用在普通方法上,能夠鎖住當前物件。
- 用在靜態方法上,能夠鎖住類
- 用在程式碼塊上,鎖住的是
synchronized
()裡的物件
在JDK6之前,synchronized
使用的是重量級鎖制,在之後synchronized
加入了鎖膨脹機制,顯著提升了synchronized
關鍵字的效率。
基於synchronized
關鍵字,我們來了解下幾種類別的鎖,並且講解synchronized
的鎖膨脹機制。
synchronized
鎖是非公平鎖。並且一個被synchronized
鎖住的物件或類,就是一把鎖。
另外一提,所有鎖都是儲存在Java物件頭裡的,Java物件頭裡的Mark Word裡預設儲存物件的HashCode,分代年齡和鎖標記位。也就是說Mark Word記錄了鎖的狀態
二、鎖膨脹機制與幾類鎖
鎖膨脹是不可逆的
2.1 偏向鎖
synchronized
在JDK1.6以後預設開啟偏向鎖
,synchronized
最初都是偏向鎖
表現:一個執行緒獲取鎖成功後,會在物件頭裡記錄執行緒ID,以後該執行緒獲取和釋放鎖都沒有任何花費。(因為該鎖已經被繫結在該執行緒上了,且在膨脹前不會改變),如果其他執行緒嘗試獲取這個鎖,偏向鎖
將會膨脹為輕量鎖
。
優點:在只有一個執行緒使用鎖的時候獲取和退出鎖沒有任何花費
缺點:鎖競爭激烈會很快升級為輕量鎖
,那麼維持偏向鎖
的過程就是在浪費計算機資源。(不過因為偏向鎖
本身就很輕量,因此浪費的資源並不多)
小結:只有一個執行緒使用鎖的情況下,synchronized
使用的鎖為偏向鎖
。
如果鎖競爭激烈,可以通過配置JDK禁用偏向鎖
。
2.2 輕量鎖
一把鎖不止一個執行緒使用,則
偏向鎖
膨脹為輕量鎖
表現:執行緒獲取輕量鎖
時,會直接用CAS
修改物件頭裡鎖的記錄,如果修改失敗,代表此時鎖存在多個執行緒的競爭,輕量鎖
將會膨脹為重量鎖
。
優點:線上程之間使用鎖不存在競爭時,一次CAS
操作就能獲取和退出鎖
缺點:與偏向鎖
類似
小結:只要一把鎖不止一個執行緒獲取過,偏向鎖
就會膨脹為輕量鎖
2.3 重量鎖
一把鎖存在多執行緒競爭,則
輕量鎖
開始自旋,自旋一定次數後仍沒獲取鎖,則膨脹為重量鎖
(存在競爭時,輕量鎖
雖然會先自旋,但是最終往往都會膨脹為重量鎖
)
表現:執行緒獲取重量鎖
時,如果獲取失敗(即鎖已被其他執行緒獲取),則使用自適應自旋鎖
,自旋一定次數後仍沒獲取鎖,則進入阻塞佇列等待。
優點:未獲取到的鎖進入阻塞佇列,節約CPU資源。(好吧感覺其實是沒有啥優點)
缺點:重量鎖
是通過物件內部的監視器(monitor)實現,其中monitor的本質是依賴於底層作業系統的Mutex Lock實現,作業系統實現執行緒之間的切換需要從使用者態到核心態的切換,切換成本非常高。
小結:只要一把鎖存在多執行緒競爭,輕量鎖
就會膨脹為重量鎖
。
自旋鎖
synchronized
的輕量鎖
,重量鎖
,使用了自適應自旋鎖
進行效能優化
首先介紹自旋鎖
表現:執行緒獲取鎖失敗後,不會進入阻塞等待,而是再次嘗試去獲取鎖,如此反覆,直到獲取到鎖,或者自旋結束那麼會阻塞等待。
解決問題:在某些場景下,執行緒持有鎖的時間非常短。線上程獲取鎖失敗後,如果執行緒進入阻塞將會帶來執行緒上下文的切換,上下文切換的時間可能反而高於執行緒反覆嘗試獲取鎖的時間。 此時執行緒原地等待去重複獲取鎖。反而在效能上更有優勢。
缺點:
- 單核CPU沒有執行緒並行,反覆嘗試會導致程序無法繼續執行。
- 重複嘗試導致了CPU的佔用,如果CPU資源緊張的話反而會效能下降
- 如果鎖的競爭時間過長,不僅沒有效能提升,還浪費了大量CPU資源。
優化:使用自適應自旋鎖
。自適應自旋鎖會根據之前的鎖獲取記錄,優化調整自旋時間,避免造成不必要的自旋。
三、具體synchronized流程
點關注,不迷路,這是一個程式都想要關注的公眾號
相關推薦
Java多執行緒synchronized關鍵字引出的多種鎖
一、synchronized機制 synchronized關鍵字是JAVA中常用的同步功能,提供了簡單易用的鎖功能。 synchronized有三種用法,分別為: 用在普通方法上,能夠鎖住當前物件。 用在靜態方法上,能夠鎖住類 用在程式碼塊上,鎖住的是synchronized()裡的物件 在JDK6之前
Java物件鎖和類鎖全面解析(多執行緒synchronized關鍵字)
最近工作有用到一些多執行緒的東西,之前吧,有用到synchronized同步塊,不過是別人怎麼用就跟著用,並沒有搞清楚鎖的概念。最近也是遇到一些問題,不搞清楚鎖的概念,很容易碰壁,甚至有些時候自己連用沒用對都不知道。 今天把一些疑惑都解開了,寫篇文章分享給大家
Java多執行緒——synchronized使用詳解
一 前言 Java多執行緒是面試必考的知識點,哈哈,說的有點太絕對了,題外話不說那麼多了,今天我們就來了解一下Java多執行緒中的synchronized。 synchronized相信大家都看過或者用過,synchronized是Java中的關鍵字,synchronized可以
java 多執行緒synchronized鎖同步方法,同步程式碼塊
執行緒安全問題 同步和非同步 我們知道多個執行緒共享堆記憶體,當兩個或者多個執行緒呼叫同一個物件的方法操作物件成員時,因為cpu輪流執行執行緒,執行緒A剛開始操作物件方法,修改了資料,輪到執行緒B執行,執行緒B也操作物件方法,修改資料,可能又輪到執行緒A操作物件方法,接著上次執行緒A的剩餘部
深入理解Java多執行緒--synchronized的實現原理
執行緒安全是多執行緒程式設計中的一個重要的知識點,何為執行緒安全?在多執行緒併發中,有很多資料是執行緒共享的,當我們某個執行緒去操作共享資料的時候,需要先將共享資料複製到當前執行緒的記憶體空間中來,然後進行操作完畢之後再將資料更新到共享空間中去。這就造成了一個問題,當我們有多個執行緒去讀取和操作
Java學習筆記(一) Java多執行緒 synchronized同步方法
1.提出問題-例項變數非執行緒安全 如果多個執行緒同時訪問1個物件的例項變數,則可能出現"非執行緒安全"問題。 1.1 何為非執行緒安全? 我的理解是多個執行緒對一個例項變數操作會出現值被更改,不同步的情況。 1.2 舉例 1.2.1 有私有變數的類HasPr
Java學習筆記(二) Java多執行緒 synchronized同步方法-防止髒讀
1. 髒讀 在給一個物件賦值的時候進行了同步, 但是在取值的時候可能出現意外,此值已經被其他執行緒修改了,這種情況就是髒讀 1.1 PublicVar類 public class PublicVar { public String userName =
Java多執行緒synchronized與 lock同步及交替列印
synchronized與 lock 區別 1)Lock不是Java語言內建的,synchronized是Java語言的關鍵字。Lock是一個介面,通過這個介面的實現類可以實現同步訪問; 2)採用synchronized不需要手動釋放鎖,當synchronized方法或者sync
JAVA多執行緒synchronized詳解
Java語言的關鍵字,當它用來修飾一個方法或者一個程式碼塊的時候,能夠保證在同一時刻最多隻有一個執行緒執行該段程式碼。 當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程
java多執行緒synchronized的使用及死鎖的造成和解鎖
1.synchronized在不同位置鎖的內容 實際就是鎖物件和鎖類(不準確的說法)的區別。通常的用法都好理解,需要注意的是synchronized Method。如果方法是static的,那麼很好理解,實際上也是鎖了class;如果是普通方法則向當於物件鎖s
Java多執行緒Synchronized的注意細節
最近做java多執行緒開發處理中發現synchronized的使用還是有一些細節問題要注意的。 1.synchronized與static synchronized 的區別 synchronized是對類的當前例項進行加鎖,防止其他執行緒同時訪問該類的該例項的所有synch
Java多執行緒synchronized、ReentrantLock、ReentrantReadWriteLock 和StampedLock 的對比
synchronized是在JVM層面上實現的,可以通過一些監控工具控制synchronized的鎖定,當代碼出現異常時,JVM會自動釋放鎖定。當只有少量競爭者的時候,synchronized是一個很
java 多執行緒 synchronized鎖重入
public class Service { synchronized public void service1(){ System.out.println("service1"); service2(); } syn
java多執行緒之Lock--顯式鎖
Lock與Synchronized簡介 Synchornized相信大家用的已經比較熟悉了,這裡我就不介紹它的用法了 Synchronized被稱為同步鎖或者是隱式鎖,隱式鎖與顯式鎖區別在於,隱式鎖的獲取和釋放都需要出現在一個塊結構中,而且是有順序的,獲取鎖的順序和釋放鎖的順序必須相反,就是說,
java多執行緒之(二)鎖
一,鎖 在物件的建立時java會為每個object物件分配一個monitor( 監視器或者監視鎖),當某個物件的同步方法(synchronized methods )被多個執行緒呼叫時,該物件的monitor將負責處理這些訪問的併發獨佔要求。 當一個執行緒呼叫一個物件的同步方法時(sy
java多執行緒系列3:悲觀鎖和樂觀鎖
1.悲觀鎖和樂觀鎖的基本概念 悲觀鎖: 總是認為當前想要獲取的資源存在競爭(很悲觀的想法),因此獲取資源後會立刻加鎖,於是其他執行緒想要獲取該資源的時候就會一直阻塞直到能夠獲取到鎖; 在傳統的關係型資料庫中,例如行鎖、表鎖、讀鎖、寫鎖等,都用到了悲觀鎖。還有java中的同步關鍵字Synchroniz
java多執行緒程式設計之讀寫鎖設計高效能快取器
解決多執行緒執行緒安全問題的主要方法是通過加鎖的方式來實現,當多個執行緒對某個變數進行讀取或寫入的時候通過加鎖來限定只有當前獲取鎖許可權的執行緒才可以對資料進行讀寫,當該執行緒訪問完畢釋放鎖之後其他阻
入坑JAVA多執行緒併發(六)死鎖
在多執行緒的中,因為要保證執行緒安全,需要對一些操作進行加鎖,但是如果操作不當,會造成死鎖,導致程式無法執行下去。 形成死鎖的場景:如果有兩個執行緒,執行緒1和執行緒2,執行緒1執行,獲得鎖A,執行緒2執行,獲得B,執行緒1等待鎖B的釋放,執行緒2等待
Java多執行緒-53-ReentrantLock類-互斥鎖
前面文章末尾,我們提到wait會釋放鎖,而sleep不會釋放鎖。那麼什麼是鎖,鎖就是把執行緒鎖住。也就是執行緒能被鎖住,當然還有釋放鎖。這篇來了解下ReentrantLock類,中文的意思就是互斥鎖。主要學習這個類的lock()獲取鎖和unlock()釋放鎖。 互斥鎖程式碼舉例 我們先來
Java多執行緒中的物件互斥鎖
1、為什麼會有鎖? 在看執行緒同步的問題之前,我們先看一個生活中的小例子: 我拿著銀行卡去ATM取錢,假如我的卡里有3000塊,我要取走2000,這個時候,ATM會去銀行的資料庫裡查詢我的賬戶是否有2000以上的餘額,如果有,就會讓我取走,不幸的是,這個時候