java多線程編程之使用Synchronized塊同步方法
synchronized關(guān)鍵字有兩種用法。第一種就是在《使用Synchronized關(guān)鍵字同步類方法》一文中所介紹的直接用在方法的定義中。另外一種就是synchronized塊。我們不僅可以通過synchronized塊來同步一個(gè)對(duì)象變量。也可以使用synchronized塊來同步類中的靜態(tài)方法和非靜態(tài)方法。
synchronized塊的語法如下:
public void method()
{
… …
synchronized(表達(dá)式)
{
… …
}
}
一、非靜態(tài)類方法的同步
從《使用Synchronized關(guān)鍵字同步類方法》一文中我們知道使用synchronized關(guān)鍵字來定義方法就會(huì)鎖定類中所有使用synchronzied關(guān)鍵字定義的靜態(tài)方法或非靜態(tài)方法,但這并不好理解。而如果使用synchronized塊來達(dá)到同樣的效果,就不難理解為什么會(huì)產(chǎn)生這種效果了。如果想使用synchronized塊來鎖定類中所有的同步非靜態(tài)方法,需要使用this做為synchronized塊的參數(shù)傳入synchronized塊國,代碼如下:
通過synchronized塊同步非靜態(tài)方法
public class SyncBlock
{
public void method1()
{
synchronized(this) // 相當(dāng)于對(duì)method1方法使用synchronized關(guān)鍵字
{
… …
}
}
public void method2()
{
synchronized(this) // 相當(dāng)于對(duì)method2方法使用synchronized關(guān)鍵字
{
… …
}
}
public synchronized void method3()
{
… …
}
}
在上面的代碼中的method1和method2方法中使用了synchronized塊。而第017行的method3方法仍然使用synchronized關(guān)鍵字來定義方法。在使用同一個(gè)SyncBlock類實(shí)例時(shí),這三個(gè)方法只要有一個(gè)正在執(zhí)行,其他兩個(gè)方法就會(huì)因未獲得同步鎖而被阻塞。在使用synchronized塊時(shí)要想達(dá)到和synchronized關(guān)鍵字同樣的效果,必須將所有的代碼都寫在synchronized塊中,否則,將無法使當(dāng)前方法中的所有代碼和其他的方法同步。
除了使用this做為synchronized塊的參數(shù)外,還可以使用SyncBlock.this作為synchronized塊的參數(shù)來達(dá)到同樣的效果。
在內(nèi)類(InnerClass)的方法中使用synchronized塊來時(shí),this只表示內(nèi)類,和外類(OuterClass)沒有關(guān)系。但內(nèi)類的非靜態(tài)方法可以和外類的非靜態(tài)方法同步。如在內(nèi)類InnerClass中加一個(gè)method4方法,并使method4方法和SyncBlock的三個(gè)方法同步,代碼如下:
使內(nèi)類的非靜態(tài)方法和外類的非靜態(tài)方法同步
public class SyncBlock
{
… …
class InnerClass
{
public void method4()
{
synchronized(SyncBlock.this)
{
… …
}
}
}
… …
}
在上面SyncBlock類的新版本中,InnerClass類的method4方法和SyncBlock類的其他三個(gè)方法同步,因此,method1、method2、method3和method4四個(gè)方法在同一時(shí)間只能有一個(gè)方法執(zhí)行。
Synchronized塊不管是正常執(zhí)行完,還是因?yàn)槌绦虺鲥e(cuò)而異常退出synchronized塊,當(dāng)前的synchronized塊所持有的同步鎖都會(huì)自動(dòng)釋放。因此,在使用synchronized塊時(shí)不必?fù)?dān)心同步鎖的釋放問題。
二、靜態(tài)類方法的同步
由于在調(diào)用靜態(tài)方法時(shí),對(duì)象實(shí)例不一定被創(chuàng)建。因此,就不能使用this來同步靜態(tài)方法,而必須使用Class對(duì)象來同步靜態(tài)方法。代碼如下:
通過synchronized塊同步靜態(tài)方法
public class StaticSyncBlock
{
public static void method1()
{
synchronized(StaticSyncBlock.class)
{
… …
}
}
public static synchronized void method2()
{
… …
}
}
在同步靜態(tài)方法時(shí)可以使用類的靜態(tài)字段class來得到Class對(duì)象。在上例中method1和method2方法同時(shí)只能有一個(gè)方法執(zhí)行。除了使用class字段得到Class對(duì)象外,還可以使用實(shí)例的getClass方法來得到Class對(duì)象。上例中的代碼可以修改如下:
使用getClass方法得到Class對(duì)象
public class StaticSyncBlock
{
public static StaticSyncBlock instance;
public StaticSyncBlock()
{
instance = this;
}
public static void method1()
{
synchronized(instance.getClass())
{
}
}
}
在上面代碼中通過一個(gè)public的靜態(tài)instance得到一個(gè)StaticSyncBlock類的實(shí)例,并通過這個(gè)實(shí)例的getClass方法得到了Class對(duì)象(一個(gè)類的所有實(shí)例通過getClass方法得到的都是同一個(gè)Class對(duì)象,因此,調(diào)用任何一個(gè)實(shí)例的getClass方法都可以)。我們還可以通過Class對(duì)象使不同類的靜態(tài)方法同步,如Test類的靜態(tài)方法method和StaticSyncBlock類的兩個(gè)靜態(tài)方法同步,代碼如下:
Test類的method方法和StaticSyncBlock類的method1、method2方法同步
public class Test
{
public static void method()
{
synchronized(StaticSyncBlock.class)
{
}
}
}
注意:在使用synchronized塊同步類方法時(shí),非靜態(tài)方法可以使用this來同步,而靜態(tài)方法必須使用Class對(duì)象來同步。它們互不影響。當(dāng)然,也可以在非靜態(tài)方法中使用Class對(duì)象來同步靜態(tài)方法。但在靜態(tài)方法中不能使用this來同步非靜態(tài)方法。這一點(diǎn)在使用synchronized塊同步類方法時(shí)應(yīng)注意。
相關(guān)文章
SpringSecurity中的Filter Chain(過濾器鏈)
Spring Security的Filter Chain是由一系列過濾器組成的管道,每個(gè)過濾器執(zhí)行特定的安全功能,Spring Security能夠提供強(qiáng)大而靈活的安全控制機(jī)制,從而保護(hù)你的應(yīng)用程序不受各種網(wǎng)絡(luò)安全威脅的侵害,本文介紹SpringSecurity中的Filter Chain,感興趣的朋友跟隨小編一起看看吧2024-06-06
Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之哈希算法實(shí)現(xiàn)
哈希表本質(zhì)是一種(key,value)結(jié)構(gòu),由此我們可以聯(lián)想到,能不能把哈希表的key映射成數(shù)組的索引index呢?如果這樣做的話那么查詢相當(dāng)于直接查詢索引,查詢時(shí)間復(fù)雜度為O(1),其實(shí)這也正是當(dāng)key為int型時(shí)的做法,將key通過某種做法映射成index,從而轉(zhuǎn)換成數(shù)組結(jié)構(gòu)2022-02-02
Java處理時(shí)間格式CST和GMT轉(zhuǎn)換方法示例
這篇文章主要給大家介紹了關(guān)于Java處理時(shí)間格式CST和GMT轉(zhuǎn)換方法的相關(guān)資料,相信很多小伙伴在時(shí)間格式轉(zhuǎn)換的時(shí)候非常頭疼,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
Java基礎(chǔ)之打印萬年歷的簡單實(shí)現(xiàn)(案例)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)之打印萬年歷的簡單實(shí)現(xiàn)(案例)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07
最新SpringCloud?Stream消息驅(qū)動(dòng)講解
SpringCloud Stream 是一個(gè)構(gòu)建消息驅(qū)動(dòng)微服務(wù)的框架,通過 SpringCloud Stream 連接消息中間件,以實(shí)現(xiàn)消息事件驅(qū)動(dòng),這篇文章主要介紹了SpringCloud?Stream消息驅(qū)動(dòng),需要的朋友可以參考下2022-11-11

