synchronized关键字的底层原理以及JDK1.6之后的底层优化
synchronized關鍵字底層原理屬于JVM層面。
1. synchronized關鍵字修飾同步代碼塊,synchronized同步代碼塊的實現使用的是monitorenter和monitorexit指令,monitorenter指令作用于同步代碼塊開始的地方,monitorexit作用于同步代碼塊結束的地方。當執行monitorenter指令的時候,線程試圖獲取當前鎖對象,也就是獲取monitor的持有權,只有當鎖計數器為0的時候,才可以獲取到,鎖計數器自增,變為1,當執行到monitorexit指令的時候,鎖計數器減一,變為0,釋放鎖對象。如果獲取當前鎖對象失敗,那么當前線程則阻塞等待,直到鎖被另一個線程釋放。
2. synchronized關鍵字修飾同步方法,synchronized同步方法的實現沒有monitorenter和monitorexit指令,取代的是ACC_SYNCHRONIZED標識,該標識表示該方法是一個同步方法,JVM根據這個標識來辨別是不是一個同步方法,進而進行同步調用。
JDK1.6之后對synchronized底層做了優化,如偏向鎖、輕量級鎖、自旋鎖。自適應自旋鎖、鎖消除和鎖粗化等技術減少鎖操作的開銷。
偏向鎖:引入偏向鎖和引入輕量級鎖的目的很像,都是為了在沒有多線程競爭的前提下,減少傳統的重量級鎖使用操作系統互斥量產生的性能消耗。但不同的是:輕量級鎖在沒有競爭的情況下,使用CAS操作來代替使用互斥量,而偏向鎖是將整個同步都消除掉。偏向鎖偏向于第一個獲取它的線程,在接下來的執行中,該鎖如果沒有被其他線程獲取,那么持有偏向鎖的線程就不需要再同步了。對于鎖競爭激烈的場景,偏向鎖就失效了,因為這樣的場景可能每次申請鎖的線程都不相同。偏向鎖失敗后,不會立即膨脹為重量級鎖,而是先升級為輕量級鎖。
輕量級鎖:偏向鎖失敗以后,不會直接升級為重量級鎖,先使用輕量級鎖優化。輕量級鎖的本意是在沒有多線程競爭的前提下,減少傳統的重量級鎖使用操作系統互斥量產生的性能消耗,因為使用輕量級鎖不需要申請互斥量,輕量級鎖加鎖和解鎖都需要CAS操作。輕量級鎖可以提升程序同步性能的依據是:對于絕大部分鎖在同步周期內是不存在競爭的。如果沒有競爭,輕量級鎖使用CAS操作避免了互斥操作的開銷。但如果存在競爭,除了CAS操作,還有互斥操作,增加了性能消耗,比重量級鎖還慢,會很快升級。
自旋鎖和自適應自旋:因為一般線程持有鎖的時間不會很長,所以這時候將線程掛起再恢復,太麻煩,所以為了讓別的線程等待,就執行一個忙循環,也叫自旋,默認次數是10次,如果還是沒有獲得鎖,就掛起線程。但角度看。jdk1.6之后引入了自適應自旋鎖,就是自旋的時間不固定了,而是由前一次同一個鎖上的自旋時間和擁有狀態決定。
鎖消除和鎖粗化:虛擬機檢測到共享的資源數據不需要競爭了,就會消除鎖;將同步快的作用范圍限制的盡可能小。
總結
以上是生活随笔為你收集整理的synchronized关键字的底层原理以及JDK1.6之后的底层优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: __wakeup绕过版本_PHP__wa
- 下一篇: (转)F5的工作原理