Java並發機制及鎖的實現原理

來源:互聯網
上載者:User

標籤:swa   zed   使用   多個   第一個   所有權   輸送量   就是   被佔用   

同步的基本思想

為了保證共用資料在同一時刻只被一個線程使用,我們有一種很簡單的實現思想,就是 

在共用資料裡儲存一個鎖 ,當沒有線程訪問時,鎖是空的。

當有第一個線程訪問時,就 在鎖裡儲存這個線程的標識 並允許這個線程訪問共用資料。

在當前線程釋放共用資料之前,如果再有其他線程想要訪問共用資料,就要 等待鎖釋放 。

 

  • 在共用資料裡儲存一個鎖
  • 在鎖裡儲存這個線程的標識
  • 其他線程訪問已加鎖共用資料要等待鎖釋放

 

Jvm同步的實現

jvm中有以下三種鎖(由上到下越來越“重量級”):

  1. 偏向鎖
  2. 輕量級鎖
  3. 重量級鎖

 

 

 

重量級鎖

Synchronized 原理

我們直接參考JVM規範中描述:每個對象有一個監視器鎖(monitor)

 

當monitor被佔用時就會處於鎖定狀態,線程執行monitorenter指令時嘗試擷取monitor的所有權,過程如下:

 

1、如果monitor的進入數為0,則該線程進入monitor,然後將進入數設定為1,該線程即為monitor的所有者。

 

2、如果線程已經佔有該monitor,只是重新進入,則進入monitor的進入數加1.

 

3.如果其他線程已經佔用了monitor,則該線程進入阻塞狀態,直到monitor的進入數為0,再重新嘗試擷取monitor的所有權。

 

 

 

Synchronized的語義底層是通過一個monitor的對象來完成,其實wait/notify等方法也依賴於monitor對象,

 

這就是為什麼只有在同步的塊或者方法中才能調用wait/notify等方法,否則會拋出java.lang.IllegalMonitorStateException的異常的原因。

 

 

Synchronized是通過對象內部的一個叫做監視器鎖(monitor)來實現的。

但是監視器鎖本質又是依賴於底層的作業系統的互斥鎖(Mutex Lock)來實現的。而作業系統實現線程之間的切換這就需要從使用者態轉換到核心態,這個成本非常高,狀態之間的轉換需要相對比較長的時間,這就是為什麼Synchronized效率低的原因。

因此,這種依賴於作業系統互斥鎖(Mutex Lock)所實現的鎖我們稱之為“重量級鎖”。

 

輕量級鎖 

  鎖的狀態總共有四種:無鎖狀態、偏向鎖、輕量級鎖和重量級鎖。

   JDK 1.6中預設是開啟偏向鎖和輕量級鎖的,我們也可以通過-XX:-UseBiasedLocking來禁用偏向鎖。

 

輕量級鎖的核心思想就是“被加鎖的代碼不會發生並發,如果發生並發,那就膨脹成重量級鎖(膨脹指的鎖的重量級上升,一旦升級,就不會降級了)”。

   輕量級鎖依賴了一種叫做CAS(compare and swap)的操作。

 

術語定義
術語 英文 說明
CAS Compare and Swap

比較並設定。

用於在硬體層面上提供原子性操作

在 Intel 處理器中,比較並交換通過指令cmpxchg實現。比較是否和給定的數值一致,如果一致則修改,不一致則不修改。

偏向鎖

根據輕量級鎖的實現,我們知道雖然輕量級鎖不支援“並發”,遇到“並發”就要膨脹為重量級鎖,但是輕量級鎖可以支援多個線程以串列的方式訪問同一個加鎖對象。

比如A線程可以先擷取對象o的輕量鎖,然後A釋放了輕量鎖,這個時候B線程來擷取o的輕量鎖,是可以成功擷取得,以這種方式可以一直串列下去。

 

之所以能實現這種串列,是因為有一個釋放鎖的動作。那麼假設有一個加鎖的java方法,這個方法在啟動並執行時候其實從始至終只有一個線程在調用,但是每次調用完卻也要釋放鎖,下次調用還要重新獲得鎖。

那麼我們能不能做一個假設:“假設加鎖的代碼從始至終就只有一個線程在調用,如果發現有多於一個線程調用,再膨脹成輕量級鎖也不遲”。這個假設,就是偏向鎖的核心思想。

   偏向鎖依賴了一種叫做CAS(compare and swap)的操作。

 

總結 

  本文重點介紹了JDk中採用輕量級鎖和偏向鎖等對Synchronized的最佳化,

   但是這兩種鎖也不是完全沒缺點的,比如競爭比較激烈的時候,不但無法提升效率,反而會降低效率,因為多了一個鎖定擴大的過程,這個時候就需要通過-XX:-UseBiasedLocking來禁用偏向鎖。下面是這幾種鎖的對比:

優點

缺點

適用情境

偏向鎖

加鎖和解鎖不需要額外的消耗,和執行非同步方法比僅存在納秒級的差距。

如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗

適用於只有一個線程訪問同步塊情境。

輕量級鎖

競爭的線程不會阻塞,提高了程式的響應速度。

如果始終得不到鎖競爭的線程使用自旋會消耗CPU

追求回應時間

同步塊執行速度非常快。

重量級鎖

線程競爭不使用自旋,不會消耗CPU。

線程阻塞,回應時間緩慢。

追求輸送量

同步塊執行速度較長。

參考如下:

 

51932179

 

Java並發機制及鎖的實現原理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.