synchronized 是Java併發編程中很是重要的角色,這裏簡單記錄對於其原理的學習html
synchronized 具備互斥性,能夠保證只有一個線程能夠訪問同步塊編程
synchronized 修飾普通方法,鎖爲當前實例對象安全
synchronized 修飾靜態方法,鎖爲當前類的Class對象併發
synchronized 修飾同步方法塊,鎖爲代碼塊括號中填寫的對象性能
monitorenter
和monitorexit
兩條指令控制同步代碼塊的訪問ACC_SYNCHRONIZED
標誌符控制(也能夠經過上述兩條指令來實現)全部Java對象都會有一個monitor,當monitor被持有後,對象就處於鎖定狀態。當執行到monitorenter指令時,線程會嘗試獲取對象的monitor,而執行monitorexit後會釋放對象的monitor學習
Java SE 1.6爲了下降鎖的獲取、釋放形成的性能損耗,增長了偏向鎖、輕量級鎖。鎖的級別由高到低依次爲無鎖狀態、偏向鎖、輕量級鎖、重量級鎖,鎖能夠升級,但不能夠降級優化
內容操作系統
鎖由同一線程屢次獲取時,會在對象頭中記錄線程ID,並在以後對同步塊的訪問時,不須要進行CAS操做來加鎖、解鎖。線程
Mark Word狀態3d
Mark Word記錄於對象頭,存儲對象的hashcode或鎖信息
這裏補充無鎖狀態的Mark Word狀態
鎖狀態 | hashcode | 分代年齡 | 是否偏向鎖 | 鎖標誌位 |
---|---|---|---|---|
無鎖狀態 | 對象的hashcode | 對象分代年齡 | 0 | 01 |
偏向鎖狀態的Mark Word狀態
鎖狀態 | Thread ID | epoch | 分代年齡 | 是否偏向鎖 | 鎖標誌位 |
---|---|---|---|---|---|
偏向鎖 | 記錄指向的線程id | epoch | 對象分代年齡 | 1 | 01 |
加鎖與解鎖
內容
輕量級鎖是經過自旋實現非阻塞同步,屬於樂觀鎖,能夠膨脹爲重量級鎖
Mark Word狀態
鎖狀態 | 記錄 | 鎖標誌位 |
---|---|---|
輕量級鎖 | 指向棧中鎖記錄的指針 | 00 |
加鎖與解鎖
加鎖
解鎖
內容
鎖升級爲重量級鎖後,其餘試圖獲取鎖的線程均會被阻塞,等待持有鎖的線程釋放鎖後,被喚醒的線程會開始競爭獲取鎖。
重量級鎖是一種互斥鎖,其依賴於對象內部的monitor鎖實現,在操做系統層面是經過MutexLock實現的。雖然在阻塞時不須要耗費CPU資源,可是線程從阻塞狀態喚醒須要操做系統完成狀態轉換(用戶態到內核態),耗時較長。
Mark Word狀態
鎖狀態 | 記錄 | 鎖標誌位 |
---|---|---|
重量級鎖 | 指向互斥量(重量級鎖)的指針 | 10 |
對比表參考《Java併發編程的藝術》
鎖 | 優勢 | 缺點 | 適用場景 |
---|---|---|---|
偏向鎖 | 加鎖和解鎖不須要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 | 若是線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 | 適用於只有一個線程訪問同步塊的場景 |
輕量級鎖 | 非阻塞同步,提升程序響應速度 | 自旋消耗CPU資源 | 追求響應時間,同步方法執行速度較快 |
重量級鎖 | 線程阻塞時不須要消耗CPU | 線程阻塞,響應時間緩慢 | 追求吞吐量,同步塊執行時間較長 |
若有問題,還請指出