您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中的鎖有哪些”,在日常操作中,相信很多人在Java中的鎖有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java中的鎖有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Java中的鎖從宏觀來分,分為悲觀鎖、和樂觀鎖。
樂觀鎖是一種樂觀思想,即認為讀多寫少,遇到并發寫的可能性低,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,采取在寫時先讀出當前版本號,然后加鎖操作(比較跟上一次的版本號,如果一樣則更新),如果失敗則要重復讀-比較-寫的操作。
java中的樂觀鎖基本都是通過CAS操作實現的,CAS是一種更新的原子操作,比較當前值跟傳入值是否一樣,一樣則更新,否則失敗。
悲觀鎖是就是悲觀思想,即認為寫多,遇到并發寫的可能性高,每次去拿數據的時候都認為別人會修改,所以每次在讀寫數據的時候都會上鎖,這樣別人想讀寫這個數據就會block直到拿到鎖。java中的悲觀鎖就是synchronized,AQS框架下的鎖則是先嘗試cas樂觀鎖去獲取鎖,獲取不到,才會轉換為悲觀鎖,如RetreenLock。
Java的線程是映射到操作系統原生線程之上的,如果要阻塞或喚醒一個線程就需要操作系統介入,需要在用戶態與核心態之間切換,這種切換會消耗大量的系統資源,因為用戶態與內核態都有各自專用的內存空間,專用的寄存器等,用戶態切換至內核態需要傳遞給許多變量、參數給內核,內核也需要保護好用戶態在切換時的一些寄存器值、變量等,以便內核態調用結束后切換回用戶態繼續工作。
如果線程狀態切換是一個高頻操作時,這將會消耗很多CPU處理時間;
如果對于那些需要同步的簡單的代碼塊,獲取鎖掛起操作消耗的時間比用戶代碼執行的時間還要長,這種同步策略的選擇就很不明智。
synchronized會導致爭用不到鎖的線程進入阻塞狀態,所以說它是Java語言中一個重量級的同步操縱,被稱為重量級鎖,為了緩解上述性能問題,JVM從1.5開始,引入了輕量鎖與偏向鎖,默認啟用了自旋鎖,他們都屬于樂觀鎖。
明確java線程切換的代價,是理解java中各種鎖的優缺點的基礎之一。
markword是java對象數據結構中的一部分,對象的markword和java各種類型的鎖密切相關;
markword數據的長度在32位和64位的虛擬機(未開啟壓縮指針)中分別為32bit和64bit,它的最后2bit是鎖狀態標志位,用來標記當前對象的狀態,對象的所處的狀態,決定了markword存儲的內容,如下表所示:
狀態 | 標志位 | 存儲內容 |
---|---|---|
未鎖定 | 01 | 對象哈希碼、對象分代年齡 |
輕量級鎖定 | 00 | 指向鎖記錄的指針 |
膨脹(重量級鎖定) | 10 | 執行重量級鎖定的指針 |
GC標記 | 11 | 空(不需要記錄信息) |
可偏向 | 01 | 偏向線程ID、偏向時間戳、對象分代年齡 |
32位虛擬機在不同狀態下markword結構如下所示:
鎖狀態 | 25bit | 4bit | 1bit | 2bit | |
23bit | 2bit | 是否是偏向鎖 | 鎖標志位 | ||
輕量級鎖 | 指向棧中鎖記錄的指針 | 00 | |||
重量級鎖 | 指向互斥量(重量級鎖)的指針 | 10 | |||
GC標記 | 空 | 11 | |||
偏向鎖 | 線程ID | Epoch | 對象分代年齡 | 1 | 01 |
無鎖 | 對象的hashCode | 對象分代年齡0 | 0 | 01 |
前面提到了java的4種鎖,他們分別是重量級鎖、自旋鎖、輕量級鎖和偏向鎖,不同的鎖有不同特點,每種鎖只有在其特定的場景下,才會有出色的表現,java中沒有哪種鎖能夠在所有情況下都能有出色的效率,引入這么多鎖的原因就是為了應對不同的情況。
重量級鎖是悲觀鎖的一種,自旋鎖、輕量級鎖與偏向鎖屬于樂觀鎖。
到此,關于“Java中的鎖有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。