Java併發編程(1):可重入內置鎖

每一個Java對象均可以用作一個實現同步的鎖,這些鎖被稱爲內置鎖或監視器鎖。線程在進入同步代碼塊以前會自動獲取鎖,而且在退出同步代碼塊時會自動釋放鎖。得到內置鎖的惟一途徑就是進入由這個鎖保護的同步代碼塊或方法。

當某個線程請求一個由其餘線程持有的鎖時,發出請求的線程就會阻塞。然而,因爲內置鎖是可重入的,所以若是摸個線程試圖得到一個已經由它本身持有的鎖,那麼這個請求就會成功。「重入」意味着獲取鎖的操做的粒度是「線程」,而不是調用。重入的一種實現方法是,爲每一個鎖關聯一個獲取計數值和一個全部者線程。當計數值爲0時,這個鎖就被認爲是沒有被任何線程所持有,當線程請求一個未被持有的鎖時,JVM將記下鎖的持有者,而且將獲取計數值置爲1,若是同一個線程再次獲取這個鎖,計數值將遞增,而當線程退出同步代碼塊時,計數器會相應地遞減。當計數值爲0時,這個鎖將被釋放。sql

重入進一步提高了加鎖行爲的封裝性,所以簡化了面向對象併發代碼的開發。分析以下程序:架構

 

public class Father
{
 public synchronized void doSomething(){
 ......
 }
}
 
public class Child extends Father
{
 public synchronized void doSomething(){
 ......
 super.doSomething();
 }
}

子類覆寫了父類的同步方法,而後調用父類中的方法,此時若是沒有可重入的鎖,那麼這段代碼件產生死鎖。併發

因爲Fither和Child中的doSomething方法都是synchronized方法,所以每一個doSomething方法在執行前都會獲取Child對象實例上的鎖。若是內置鎖不是可重入的,那麼在調用super.doSomething時將沒法得到該Child對象上的互斥鎖,由於這個鎖已經被持有,從而線程會永遠阻塞下去,一直在等待一個永遠也沒法獲取的鎖。重入則避免了這種死鎖狀況的發生。分佈式

同一個線程在調用本類中其餘synchronized方法/塊或父類中的synchronized方法/塊時,都不會阻礙該線程地執行,由於互斥鎖時可重入的。高併發

歡迎工做一到五年的Java工程師朋友們加入Java架構開發
: 867748702
羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、
Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,
Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)
合理利用本身每一分每一秒的時間來學習提高本身,
不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!性能

相關文章
相關標籤/搜索