關(guān)于synchronized的參數(shù)及其含義
這個(gè)想必大家都不陌生,java里面的重量級(jí)鎖。用來(lái)控制線(xiàn)程安全的。在long And long ,我剛開(kāi)始接觸java的時(shí)候 ,我就對(duì)這個(gè)關(guān)鍵詞好奇頗深。尤其是 它的參數(shù),有this的 也有靜態(tài)變量的。網(wǎng)上對(duì)這個(gè)參數(shù)解釋又太過(guò)術(shù)語(yǔ)話(huà)。
例如
作用于方法時(shí),鎖住的是對(duì)象的實(shí)例(this);
當(dāng)作用于靜態(tài)方法時(shí),鎖住的是Class實(shí)例,又因?yàn)镃lass的相關(guān)數(shù)據(jù)存儲(chǔ)在永久帶PermGen(jdk1.8則是metaspace),永久帶是全局共享的,因此靜態(tài)方法鎖相當(dāng)于類(lèi)的一個(gè)全局鎖,會(huì)鎖所有調(diào)用該方法的線(xiàn)程;
當(dāng)作用于一個(gè)靜態(tài)類(lèi)的時(shí)候,不管是不是本身內(nèi)部的靜態(tài)類(lèi),還是別人的靜態(tài)類(lèi),都可以完成鎖住的效果(ps 上鎖的時(shí)候,相當(dāng)于一群人 拿把鎖找個(gè)東西上鎖
synchronized作用于一個(gè)對(duì)象實(shí)例時(shí),鎖住的是所有以該對(duì)象為鎖的代碼塊。
這不管是對(duì)于初學(xué)者,還是老鳥(niǎo) 。都感覺(jué)沉長(zhǎng)無(wú)味。
最近,我的項(xiàng)目涉及到這一塊,我對(duì)這個(gè)方法有了頓悟,寫(xiě)下來(lái) 傳之后世
我對(duì)這個(gè)參數(shù)的理解是這樣的。
synchronized(獲取鎖的地方){
工作內(nèi)容
}
是的 ,你們沒(méi)看錯(cuò) ()里面的就是一個(gè)“獲取鎖的地方”。{ }里面是工作內(nèi)容。 他們有這幾條關(guān)系。
- 獲取鎖的地方 和 工作內(nèi)容 是不必需要 有任何關(guān)聯(lián)的。 可以有關(guān)聯(lián),但沒(méi)有關(guān)聯(lián) 也沒(méi)事
- 獲取鎖的地方 :只是一個(gè)讓synchronized 整體 放置鎖的地方,一個(gè)“獲取鎖的地方” 只有一把鎖。**
- 工作內(nèi)容: 要進(jìn)行工作的**前提是 synchronized整體,找到一個(gè)“獲取鎖的地方”,在 “獲取鎖的地方” 獲取到了鎖, 如果 “獲取鎖的地方”的鎖,已經(jīng)被別人拿去了,那么就只能等待別人 把鎖還給 “獲取鎖的地方”。然后 再獲取鎖。
- synchronized 會(huì)使用運(yùn)行工作內(nèi)容的前提,必須獲取到鎖。這個(gè)意思呢,就是例如,當(dāng)前線(xiàn)程synchronized 獲取到了objec A的鎖,那么其他線(xiàn)程還可以更改 A 進(jìn)行操作么?。 這個(gè)得到分兩種情況,如果其他線(xiàn)程代碼 是被synchronized 所包裹的,那么只能等 objec A被釋放了,才能更改。如果,其他線(xiàn)程代碼沒(méi)有被synchronized包裹,她可以不需要有鎖,就可以對(duì)objec A進(jìn)行操作。
解釋
先打個(gè)比方,我們把 synchronized這個(gè)看成一個(gè)整體,那么在多線(xiàn)程的時(shí)候,就會(huì)有很多個(gè) synchronized整體。 這個(gè)整體開(kāi)始工作的前提是 它可以從 “獲取鎖的地方”拿到鎖。那么他就可以做工作了。如果 想要 “獲取鎖的地方”的鎖,已經(jīng)被別人拿走了。那么只能等別人把鎖換回來(lái),才行。。
上面這個(gè)還是有點(diǎn)抽象。就這么說(shuō)吧 在程序運(yùn)行多線(xiàn)程的,會(huì)產(chǎn)生好多synchronized整體。就叫小明,小紅,小芳,小花…等。他們現(xiàn)在手中沒(méi)有鎖,只有手中有鎖的時(shí)候 才可以工作。 現(xiàn)在小明,小紅他們來(lái)到工作的地方。獲取鎖的地方就是路邊的一棵樹(shù)::注意現(xiàn)在路邊只有這一棵樹(shù)。小紅搶先一步將樹(shù)上的鎖拿走了。然后小紅工作去了(她的工作 不用和樹(shù)有關(guān)系,她可以砍樹(shù),也可以去路邊掃地 )。小明,小芳等其他人,因?yàn)闆](méi)地方獲取鎖(只有一棵樹(shù) 并且樹(shù)的鎖 已經(jīng)被小紅拿走了)。所以只能在原地等待 ,小紅工作做完了 把鎖還給樹(shù) ,小明,小芳才有機(jī)會(huì)進(jìn)行工作。、
注意: 上面是路邊只有一棵樹(shù),如果存在好幾顆樹(shù)的話(huà),那么小明,小紅他們就可以同時(shí)放置獲取鎖 一個(gè)數(shù)對(duì)應(yīng)一個(gè)鎖,多個(gè)樹(shù)就多個(gè)鎖。這個(gè)對(duì)應(yīng)于類(lèi)的實(shí)例 (實(shí)例可以有好多個(gè))

驗(yàn)證
我們首先定義一個(gè)Runnable ,因?yàn)?多線(xiàn)程的話(huà) 最好還是用Runnable,至于為什么呢?百度去。
static class LockRunable implements Runnable {
private int num;
private LockNormal lockNormal;
public LockRunable(int num, LockNormal lockNormal) {
this.num = num;
this.lockNormal = lockNormal;
}
@Override
public void run() {
while (true) {
if (num <= 0) {
break;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + num--);
}
}
}
這個(gè)類(lèi)呢 接受一個(gè)整數(shù),一個(gè)LockNormal我自己定義的類(lèi),在run里面呢先對(duì) num進(jìn)行判斷小于等于0的話(huà),就退出,否則減一。 運(yùn)行一下
LockNormal lockNormal = new LockNormal();
LockRunable one = new LockRunable(15, lockNormal);
new Thread(one).start();
new Thread(one).start();
new Thread(one).start();
new Thread(one).start();
new Thread(one).start();
num竟然變成負(fù)的了,這是因?yàn)?五個(gè)線(xiàn)程同時(shí)對(duì)他進(jìn)行操作,造成的。要避免這種情況,只能一個(gè)線(xiàn)程操作的時(shí)候,別的線(xiàn)程就不能操作。
我們給程序加鎖試一下。首先定義一個(gè) 靜態(tài)成員,靜態(tài)成員有一個(gè)特點(diǎn)是系統(tǒng)初始化的,全局只有一個(gè)實(shí)例。就相當(dāng)于上面的 只有一棵樹(shù)。
static final transient Object lock = new Object();
對(duì) 工作內(nèi)容加鎖
@Override
public void run() {
while (true) {
synchronized (lock) {
if (num <= 0) {
break;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + num--);
}
}
}
}
運(yùn)行

這次就和預(yù)期結(jié)果相等了。但是 我們可發(fā)現(xiàn) 都是都是同一個(gè)線(xiàn)程進(jìn)行操作的,這是因?yàn)?sleep時(shí)候不會(huì)釋放鎖,其他線(xiàn)程也無(wú)法進(jìn)行操作
傳入實(shí)例
static class LockRunable implements Runnable {
private int num;
private LockNormal lockNormal;
public LockRunable(int num, LockNormal lockNormal) {
this.num = num;
this.lockNormal = lockNormal;
}
@Override
public void run() {
while (true) {
synchronized (lockNormal) {
if (num <= 0) {
break;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + num--);
}
}
}
}
結(jié)果:

也是同樣的結(jié)果,如果 我們傳入this的話(huà) 運(yùn)行還是一樣的結(jié)果。這就是上面樹(shù)的問(wèn)題了,不管是傳入的實(shí)例,還是this本身實(shí)例。只有能保證它們本身是唯一的,也就是“獲取鎖的地方”只有一個(gè),同一時(shí)間內(nèi)只有一個(gè)人能成功獲取到鎖 進(jìn)行工作。就和鎖靜態(tài)成員是一樣的效果如果我們 new 兩個(gè)Runnable的話(huà),并且傳入this實(shí)例的話(huà),就會(huì)有兩個(gè)“獲取鎖的地方” ,可以有兩個(gè)人同時(shí)工作。
總結(jié)
synchronized(放鎖的地方){
工作內(nèi)容
}
只要我們保證“獲取鎖的地方”是唯一的,那么在同一時(shí)刻,就只能有一個(gè)工作內(nèi)容會(huì)被執(zhí)行。如果,“獲取鎖的地方”不是唯一的(一個(gè)類(lèi)new很多實(shí)例,鎖住this實(shí)例,那么同一時(shí)刻就會(huì)有很多放鎖的地方),在同一時(shí)刻就會(huì)有好多 工作內(nèi)容被執(zhí)行。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
應(yīng)用市場(chǎng)中Java攔截器和切面的使用實(shí)例詳解
這篇文章主要介紹了應(yīng)用市場(chǎng)中Java攔截器和切面的使用實(shí)例詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
Java try-with-resource語(yǔ)法使用解析
這篇文章主要介紹了Java try-with-resource語(yǔ)法使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
SpringBoot訪(fǎng)問(wèn)windows共享文件的方法
這篇文章主要介紹了SpringBoot訪(fǎng)問(wèn)windows共享文件,項(xiàng)目使用minio存儲(chǔ)且不在同一臺(tái)服務(wù)器上,為了優(yōu)化速度決定使用windows共享功能進(jìn)行文件傳輸,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
基于Java8實(shí)現(xiàn)提高Excel讀寫(xiě)效率
這篇文章主要介紹了基于Java8實(shí)現(xiàn)提高Excel讀寫(xiě)效率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
解決@Transactional注解事務(wù)不回滾不起作用的問(wèn)題
這篇文章主要介紹了解決@Transactional注解事務(wù)不回滾不起作用的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
詳解多云架構(gòu)下的JAVA微服務(wù)技術(shù)解析
本文介紹了基于開(kāi)源自建和適配云廠(chǎng)商開(kāi)發(fā)框架兩種構(gòu)建多云架構(gòu)的思路,以及這些思路的優(yōu)缺點(diǎn)2021-05-05
java?使用BeanFactory實(shí)現(xiàn)service與dao層解耦合詳解
這篇文章主要介紹了java?使用BeanFactory實(shí)現(xiàn)service與dao層解耦合詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SSH框架網(wǎng)上商城項(xiàng)目第2戰(zhàn)之基本增刪查改、Service和Action的抽取
SSH框架網(wǎng)上商城項(xiàng)目第2戰(zhàn)之基本增刪查改、Service和Action的抽取,感興趣的小伙伴們可以參考一下2016-05-05

