java高并发之魂:Synchronize
synchronize在高并發領域可謂是元老級別了,博主最近整理了一下synchronize的用法,和簡單的概念。
概念
對象鎖:包括 方法鎖(默認鎖對象為this當前實例對象)和同步代碼塊鎖(自己指定鎖對象)
類鎖:指synchronized 修飾靜態的方法或指定鎖對象為Class對象。
用法
同步代碼塊鎖
用this鎖:
自己指定鎖:
用this時,2個線程用的是同一把鎖,可以保證串行執行。自定義2把鎖(lock1,lock2)時,由于是2個鎖對象,無法保證2個線程串行執行。
方法鎖
sysnchronized 修飾普通方法
可以保證串行執行
類鎖
java類可能有很多個對象,但只有1個class對象,所以所謂的類鎖其實就是Class對象鎖而已。(不同實例只能在同一時刻被一個對象擁有)
sysnchronized加在static方法上
sysnchronized(*.class)代碼塊
均可實現代碼的串行化執行
常見面試題
1.兩個線程同時訪問一個對象的同步方法
答案:可以實現串行化執行,因為用的是同一個對象鎖,為同一把鎖
2.兩個線程訪問的是兩個對象的同步方法
答案:不可以實現串行化執行。因為鎖對象不同,互不干擾。
3.兩個線程訪問的是synchronized的靜態方法
答案:可以實現串行執行。因為synchronized加在靜態方法上屬于類鎖,是同一個對象鎖。
4.同時訪問同步方法和非同步方法
答案:不可以實現串行執行。非同步方法不受影響。synchronized只作用的修飾的方法上。
5.訪問同一個對象的不同的普通同步方法
答案:可以實現串行。因為同一個對象,默認使用的都是this對象,為同一把鎖。
6、同時訪問靜態synchronized和非靜態synchronized方案
答案:不可以實現串行。因為靜態的鎖對象為類鎖,非靜態的為實例的對象鎖,2個鎖對象不同,互不影響。
7.方法拋出異常后會釋放鎖嗎?
答案:可以的。synchronized可以在拋異常后自動被釋放。lock是需要手動釋放的。
性質
可重入
指的是同一個線程的外層函數獲得鎖之后,內層函數可以直接再次獲取該鎖
好處:避免死鎖,提升封裝性
粒度:?
? ? ?1.同一個方法是可以重入的
? ? ?2.可重入不要求是同一個方法
? ? ?3.可重入不要求是同一個類
?
不可中斷
sysnchronized一旦這個鎖已經被別人獲得了,如果我還想獲得,我只能等待或者阻塞,直到別的線程釋放這個鎖。如果別人永遠不釋放鎖,那么我只能永遠的等下去。
相比之下: lock類可以擁有中斷能力,第一點,如果我覺得我等的時間太長了,有權中斷現在已經獲取到鎖的線程的執行。第二點,如果我覺得我等待的時間太長了不想再等了,也可以退出。
原理
查看monitor指令
通過反編譯字節碼查看原理
.java文件
反編譯:
可重入原理(加鎖次數計數器)
1.jvm 負責跟蹤對象被加鎖的次數
2.線程第一次給對象加鎖的時候,計數變為1,每當這個相同的線程在此對象上再次獲得鎖時,計數會遞增
3.每當任務離開時,計數遞減,當技術為0時候,鎖被完全釋放
可見性原理
當被sysnchronized修飾之后的方法,在退出前會把數據刷新的主內存,當下個方法進入時候會從主存中拿到最新的數據
缺陷
效率低:鎖對象釋放的情況少,試圖獲得鎖時不能設定超時,不能中斷一個正在試圖獲得鎖的線程(lock可以)
不夠靈活:加鎖和釋放的時機單一,每個鎖僅僅有單一的條件(某個對象),可能是不夠的(lock可以)
無法知道是否成功的獲取鎖
使用注意點:
鎖對象不能為空,作用域不宜過大,避免死鎖
如何選擇lock和synchronized關鍵字(避免出錯為原則)
1.如果可以都不用,而是用java.util.current包中的工具類(countdownluch。。。等)
2.如果適用,就優先使用synchronized
3.只有有必要使用lock的特性的時候才使用lock
總結
以上是生活随笔為你收集整理的java高并发之魂:Synchronize的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分子模拟的理论与实践_活动回顾 | 信息
- 下一篇: php仿bilibili视频类模板,高仿