一、synchronized含義
synchronized是Java語(yǔ)言的關(guān)鍵字,可用來(lái)給對(duì)象和方法或者代碼塊加鎖,當(dāng)它鎖定一個(gè)方法或者一個(gè)代碼塊的時(shí)候,同一時(shí)刻非常多只有一個(gè)線程執(zhí)行這段代碼。當(dāng)兩個(gè)并發(fā)線程訪問(wèn)同一個(gè)對(duì)象object中的這個(gè)加鎖同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。然而,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)加鎖代碼塊時(shí),另一個(gè)線程仍可以訪問(wèn)該object中的非加鎖代碼塊。
synchronized的作用是保證在同一時(shí)刻, 被修飾的代碼塊或方法只會(huì)有一個(gè)線程執(zhí)行,以達(dá)到保證并發(fā)安全的效果。synchronized是Java中解決并發(fā)問(wèn)題的一種最常用的方法,也是最簡(jiǎn)單的一種方法。在JDK1.5之前synchronized是一個(gè)重量級(jí)鎖,相對(duì)于j.u.c.Lock,它會(huì)顯得那么笨重,隨著Javs SE 1.6對(duì)synchronized進(jìn)行的各種優(yōu)化后,synchronized并不會(huì)顯得那么重了。
二、synchronized的作用
1、原子性
所謂原子性就是指一個(gè)操作或者多個(gè)操作,要么全部執(zhí)行并且執(zhí)行的過(guò)程不會(huì)被任何因素打斷,要么就都不執(zhí)行。被synchronized修飾的類(lèi)或?qū)ο蟮乃胁僮鞫际窃拥模驗(yàn)樵趫?zhí)行操作之前必須先獲得類(lèi)或?qū)ο蟮逆i,直到執(zhí)行完才能釋放。
2、可見(jiàn)性
可見(jiàn)性是指多個(gè)線程訪問(wèn)一個(gè)資源時(shí),該資源的狀態(tài)、值信息等對(duì)于其他線程都是可見(jiàn)的。synchronized和volatile都具有可見(jiàn)性,其中synchronized對(duì)一個(gè)類(lèi)或?qū)ο蠹渔i時(shí),一個(gè)線程如果要訪問(wèn)該類(lèi)或?qū)ο蟊仨毾全@得它的鎖,而這個(gè)鎖的狀態(tài)對(duì)于其他任何線程都是可見(jiàn)的,并且在釋放鎖之前會(huì)將對(duì)變量的修改刷新到共享內(nèi)存當(dāng)中,保證資源變量的可見(jiàn)性。
3、有序性
有序性值程序執(zhí)行的順序按照代碼先后執(zhí)行。 synchronized和volatile都具有有序性,Java允許編譯器和處理器對(duì)指令進(jìn)行重排,但是指令重排并不會(huì)影響單線程的順序,它影響的是多線程并發(fā)執(zhí)行的順序性。synchronized保證了每個(gè)時(shí)刻都只有一個(gè)線程訪問(wèn)同步代碼塊,也就確定了線程執(zhí)行同步代碼塊是分先后順序的,保證了有序性。
三、synchronized的使用
1、修飾實(shí)例方法
作用于當(dāng)前對(duì)象實(shí)例加鎖,進(jìn)入同步代碼前要獲得當(dāng)前對(duì)象實(shí)例的鎖:
synchronized void method() { //業(yè)務(wù)代碼}
2、修飾靜態(tài)方法
即給當(dāng)前類(lèi)加鎖,會(huì)作用于類(lèi)的所有對(duì)象實(shí)例 ,進(jìn)入同步代碼前要獲得 當(dāng)前 class 的鎖。因?yàn)殪o態(tài)成員不屬于任何一個(gè)實(shí)例對(duì)象,是類(lèi)成員( static 表明這是該類(lèi)的一個(gè)靜態(tài)資源,不管 new 了多少個(gè)對(duì)象,只有一份)。所以,如果一個(gè)線程 A 調(diào)用一個(gè)實(shí)例對(duì)象的非靜態(tài) synchronized 方法,而線程 B 需要調(diào)用這個(gè)實(shí)例對(duì)象所屬類(lèi)的靜態(tài) synchronized 方法,是允許的,不會(huì)發(fā)生互斥現(xiàn)象,因?yàn)樵L問(wèn)靜態(tài) synchronized 方法占用的鎖是當(dāng)前類(lèi)的鎖,而訪問(wèn)非靜態(tài) synchronized 方法占用的鎖是當(dāng)前實(shí)例對(duì)象鎖:
synchronized void staic method() { //業(yè)務(wù)代碼}
3、修飾代碼塊
指定加鎖對(duì)象,對(duì)給定對(duì)象/類(lèi)加鎖。synchronized(this|object) 表示進(jìn)入同步代碼庫(kù)前要獲得給定對(duì)象的鎖。synchronized(類(lèi).class) 表示進(jìn)入同步代碼前要獲得當(dāng)前 class 的鎖:
synchronized(this) { //業(yè)務(wù)代碼}
延伸閱讀1:synchronized 鎖的升級(jí)順序
鎖主要存在四種狀態(tài),依次是:無(wú)鎖狀態(tài)、偏向鎖狀態(tài)、輕量級(jí)鎖狀態(tài)、重量級(jí)鎖狀態(tài),鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)的重量級(jí)鎖。但是鎖的升級(jí)是單向的,也就是說(shuō)只能從低到高升級(jí),不會(huì)出現(xiàn)鎖的降級(jí)。而且這個(gè)過(guò)程就是開(kāi)銷(xiāo)逐漸加大的過(guò)程。