1. 程式人生 > >Synchronized方法鎖、物件鎖、類鎖區別

Synchronized方法鎖、物件鎖、類鎖區別

引言

synchronized,這個東西我們一般稱之為”同步鎖“,他在修飾程式碼塊的時候需要傳入一個引用物件作為“鎖”的物件。

  在修飾方法的時候,預設是當前物件作為鎖的物件
  在修飾類時,預設是當前類的Class物件作為所的物件
  故存在著方法鎖、物件鎖、類鎖 這樣的概念

那麼我們來大致看一下這三種鎖

方法鎖(synchronized修飾方法時)

通過在方法宣告中加入synchronized關鍵字來宣告synchronized方法。
synchronized 方法鎖控制對類成員變數的訪問:
每個類例項對應一把鎖
每個synchronized方法都必須獲得呼叫該方法的類例項的”鎖“方能執行,否則所屬執行緒阻塞。

方法一旦執行,就會獨佔該鎖,一直到從該方法返回時才將鎖釋放,此後被阻塞的執行緒方能獲得該鎖,從而重新進入可執行狀態。

這種機制確保了同一時刻對於每一個類的例項,其所有宣告為synchronized的成員函式中之多隻有一個處於可執行狀態,從而有效避免了類成員變數的訪問衝突。

ok,下方介紹一個火車站賣票的例子,一共1000張票,有4個視窗賣票,賣票的方法被我定義為同步的,即每個賣票過程會賣出4張票,賣完之後才允許其他視窗賣票

大家看看程式碼,體會一下


方法鎖程式碼.png
方法鎖程式碼.png

執行結果


執行結果.png
執行結果.png

執行結果多執行幾次會發現雖然執行緒的先後順序會變化,但是每一個執行緒必定先賣出4張票之後才會去接著賣剩餘的票。

下邊我們來看下物件鎖,其實方法鎖 這個就屬於物件鎖

物件鎖(synchronized修飾方法或程式碼塊)

當一個物件中有synchronized method 或synchronized block 的時候,呼叫此物件的同步方法或進入其同步區域時,就必須先獲得物件鎖。

如果此物件的物件鎖已被其他呼叫者佔用,則需要等待此鎖被釋放。(方法鎖也是物件鎖)

java的所有物件都含有一個互斥鎖,這個鎖由jvm自動獲取和釋放。

執行緒進入synchronized 方法的時候獲取該物件的鎖,當然如果已經有執行緒獲取了這個物件的鎖,那麼當前執行緒會等待;

synchronized方法正常返回或者拋異常而終止,jvm會自動釋放物件鎖。這裡也體現了用synchronized來加鎖的一個好處,即 :

方法拋異常的時候,鎖仍然可以由jvm來自動釋放

物件鎖的兩種方式
1、方法鎖


方法鎖形式.png
方法鎖形式.png

2、程式碼塊形式


程式碼塊形式.png
程式碼塊形式.png

ok,自己體會一下哦

類鎖(synchronized修飾靜態的方法或者程式碼塊)

由於一個class不論被例項化多少次,其中的靜態方法和靜態變數在記憶體中都只有一份。所以,一旦一個靜態的方法被宣告為synchronized。此類所有的例項物件在呼叫此方法,共用同一把鎖,我們稱之為類鎖。

 前方高能:重點:要考的哦

物件鎖是用來控制例項方法之間的同步,而類鎖是用來控制靜態方法(或者靜態變數互斥體)之間的同步的。

類鎖只是一個概念上的東西,並不是真實存在的,他只是用來幫助我們理解鎖定例項方法和靜態方法的區別的。
java類可能會有很多物件,但是隻有一個Class(位元組碼)物件,也就是說類的不同例項之間共享該類的Class物件。Class物件其實也僅僅是1個java物件,只不過有點特殊而已。
由於每個java物件都有1個互斥鎖,而類的靜態方法是需要Class物件。所以所謂的類鎖,只不過是Class物件的鎖而已。
獲取類的Class物件的方法有好幾種,最簡單的是[類名.class]的方式。(百度:獲取位元組碼的三種方式)

來看下類鎖的兩種方式
方式1:


類鎖1.png
類鎖1.png

方式2:


類鎖2.png
類鎖2.png

ok,建議大家自己敲下相關程式碼,體會一下嘍~~~

有問題的可以加微信,聊騷哦

掃描二維碼,加我微信,一起探討技術問題
掃描二維碼,加我微信,一起探討技術問題