摘要:也有人稱其為同步鎖。既然是鎖,其必然有鎖的東西,下面先會簡單介紹一下,再通過一個示例代碼展示鎖了什么。從而可以證明并不是鎖定方法內(nèi)訪問的變量鎖定的是同一個監(jiān)視器對象監(jiān)視的代碼
前言
synchronized翻譯為中文的意思是同步的,它是Java中處理線程安全問題常用的關(guān)鍵字。也有人稱其為同步鎖。既然是鎖,其必然有鎖的東西,下面先會簡單介紹一下synchronized,再通過一個示例代碼展示synchronized鎖了什么。(這里先提前透露答案synchronized鎖的是代碼)
介紹 定義synchronized提供的同步機制確保了同一個時刻,被修飾的代碼塊或方法只會有一個線程執(zhí)行。
用法synchronized可以修飾方法和代碼塊:
修飾普通方法
修飾靜態(tài)方法
修飾代碼塊
根據(jù)修飾情況,分為對象鎖和類鎖:
對象鎖:
普通方法(等價于代碼塊修飾this)
代碼塊修飾的是是類的一個對象
類鎖
類方法(等價于代碼塊修飾當(dāng)前類Class對象)
代碼塊修飾的是是類Class對象
原理synchronized底層原理是使用了對象持有的監(jiān)視器(monitor)。但是同步代碼塊和同步方法的原理存在一點差異:
同步代碼塊是使用monitorenter和monitorexit指令實現(xiàn)的
同步方法是由方法調(diào)用指令讀取運行時常量池中方法的ACC_SYNCHRONIZED 標識隱式實現(xiàn),實際上還是調(diào)用了monitorenter和monitorexit指令
測試示例 計數(shù)器一個特殊的計數(shù)器,自增方法increase()被synchronized修飾,而獲取當(dāng)前值方法getCurrent()則沒有被synchronized修飾。
/** * 計數(shù)器 * @author RJH * create at 2019-03-13 */ public class Counter { /** * 全局對象,總數(shù) */ private static int i = 0; /** * 自增 * @return */ public synchronized int increase() { try { //使用休眠讓結(jié)果更明顯 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return ++i; } /** * 獲取當(dāng)前值 * @return */ public int getCurrent() { return i; } }測試代碼
使用自增線程和獲取當(dāng)前值的線程來驗證synchronized鎖的是代碼,而不是全局變量
/** * synchronized鎖了什么 * @author RJH * create at 2019-03-02 */ public class LockWhatTest { public static void main(String[] args) { Counter counter =new Counter(); IncreaseThread increaseThread1=new IncreaseThread(counter); IncreaseThread increaseThread2=new IncreaseThread(counter); GetThread getThread=new GetThread(counter); increaseThread1.start(); increaseThread2.start(); //直到increaseThread的線程啟動才執(zhí)行下一步 while (increaseThread1.getState().compareTo(Thread.State.NEW)==0 && increaseThread1.getState().compareTo(Thread.State.NEW)==0){ } getThread.start(); } /** * 自增線程 */ static class IncreaseThread extends Thread{ private Counter counter; public IncreaseThread(Counter counter) { this.counter = counter; } @Override public void run() { System.out.println("After increase:" + counter.increase()+",trigger time:"+System.currentTimeMillis()); } } /** * 獲取當(dāng)前值的線程 */ static class GetThread extends Thread{ private Counter counter; public GetThread(Counter counter) { this.counter = counter; } @Override public void run() { System.out.println("Current:"+ counter.getCurrent()+",trigger time:"+System.currentTimeMillis()); } } }執(zhí)行結(jié)果
Current:0,trigger time:1552487003845 After increase:1,trigger time:1552487008846 After increase:2,trigger time:1552487013848結(jié)果分析
從測試結(jié)果可以得知
在兩個自增線程啟動后,獲取當(dāng)前值的線程才啟動,但是獲取當(dāng)前值的線程是先被執(zhí)行完成了。
根據(jù)自增線程執(zhí)行完成的時間戳間隔可以得知,兩個自增線程是依次執(zhí)行的。
從而可以證明
synchronized并不是鎖定方法內(nèi)訪問的變量
synchronized鎖定的是同一個監(jiān)視器對象監(jiān)視的代碼
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73688.html
摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言多線程如果設(shè)計的不合理的話很可能就會出現(xiàn)死鎖當(dāng)兩個或者多個線程同事想要去獲取共享資源的鎖時但每個線程都要等其他線程把他們各自的鎖給釋放才能繼續(xù)運行這就是死鎖出現(xiàn)死鎖必須具 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github...
摘要:如何維護狀態(tài)內(nèi)部維護的讀寫狀態(tài)是由位碼表示,高位為讀狀態(tài),表示持有讀鎖的線程數(shù),低位為寫狀態(tài),表示寫鎖的重入次數(shù),狀態(tài)的改變通過實現(xiàn),保證同步。寫鎖降級到讀鎖有時擁有寫鎖的線程也希望得到讀鎖。 ReentrantReadWriteLock 如何保證同步 Java中的可重入讀寫鎖ReentrantReadWriteLock是基于AQS(AbstractQueuedSynchronizer...
摘要:了解自動鎖很早就受不了鎖的機制了每次都需要在去解鎖不僅代碼不美觀而且很麻煩我想能不能實現(xiàn)加鎖之后自動解鎖如果是可以利用析構(gòu)函數(shù)實現(xiàn)但就想了想好像可以利用的特性對象只需要實現(xiàn)接口實現(xiàn)自動鎖我了解如何利用特性寫一個自動鎖那么下面我們開始真正 了解自動鎖 很早就受不了 java 鎖的機制了,每次都需要在 finally 去解鎖, 不僅代碼不美觀,而且很麻煩 我想能不能實現(xiàn)加鎖之后自動解鎖, ...
摘要:底層是是通過對象,對象有自己的對象頭,存儲了很多信息,其中一個信息標示是被哪個線程持有。當(dāng)一個線程執(zhí)行的代碼出現(xiàn)異常時,其所持有的鎖會自動釋放。 前言 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 多線程基礎(chǔ)必要知識點!看了學(xué)習(xí)多線程事半功倍 只有光頭才能變強! 本文章主要講的是Java多線程加鎖機制,有兩種: Synchronized 顯式Lock 不得不嘮...
閱讀 2055·2021-09-30 09:47
閱讀 737·2021-09-22 15:43
閱讀 2016·2019-08-30 15:52
閱讀 2457·2019-08-30 15:52
閱讀 2581·2019-08-30 15:44
閱讀 945·2019-08-30 11:10
閱讀 3398·2019-08-29 16:21
閱讀 3325·2019-08-29 12:19