java的內(nèi)置鎖
每個(gè)java對(duì)象都可以用做一個(gè)實(shí)現(xiàn)同步的鎖,這些鎖成為內(nèi)置鎖责嚷。線(xiàn)程進(jìn)入同步代碼塊或方法的時(shí)候會(huì)自動(dòng)獲得該鎖,在退出同步代碼塊或方法時(shí)會(huì)釋放該鎖。獲得內(nèi)置鎖的唯一途徑就是進(jìn)入這個(gè)鎖的保護(hù)的同步代碼塊或方法啃勉。
java內(nèi)置鎖是一個(gè)互斥鎖,這就是意味著最多只有一個(gè)線(xiàn)程能夠獲得該鎖双妨,當(dāng)線(xiàn)程A嘗試去獲得線(xiàn)程B持有的內(nèi)置鎖時(shí)淮阐,線(xiàn)程A必須等待或者阻塞,知道線(xiàn)程B釋放這個(gè)鎖刁品,如果B線(xiàn)程不釋放這個(gè)鎖泣特,那么A線(xiàn)程將永遠(yuǎn)等待下去。
java的對(duì)象鎖和類(lèi)鎖
java的對(duì)象鎖和類(lèi)鎖在鎖的概念上基本上和內(nèi)置鎖是一致的挑随,但是状您,兩個(gè)鎖實(shí)際是有很大的區(qū)別的,對(duì)象鎖是用于對(duì)象實(shí)例方法兜挨,或者一個(gè)對(duì)象實(shí)例上的膏孟,類(lèi)鎖是用于類(lèi)的靜態(tài)方法或者一個(gè)類(lèi)的class對(duì)象上的。我們知道拌汇,類(lèi)的對(duì)象實(shí)例可以有很多個(gè)柒桑,但是每個(gè)類(lèi)只有一個(gè)class對(duì)象,所以不同對(duì)象實(shí)例的對(duì)象鎖是互不干擾的噪舀,但是每個(gè)類(lèi)只有一個(gè)類(lèi)鎖魁淳。但是有一點(diǎn)必須注意的是娃胆,其實(shí)類(lèi)鎖只是一個(gè)概念上的東西虱肄,并不是真實(shí)存在的虫给,它只是用來(lái)幫助我們理解鎖定實(shí)例方法和靜態(tài)方法的區(qū)別的
上面已經(jīng)對(duì)鎖的一些概念有了一點(diǎn)了解瞧筛,下面探討synchronized關(guān)鍵字的用法。
synchronized的用法:
synchronized修飾方法和synchronized修飾代碼塊仇奶。
下面分別分析這兩種用法在對(duì)象鎖和類(lèi)鎖上的效果貌嫡。
對(duì)象鎖的synchronized修飾方法和代碼塊:
public class TestSynchronized {
public void test1() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt2.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
myt2.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
運(yùn)行結(jié)果:
1. test2 : 4
2. test2 : 3
3. test2 : 2
4. test2 : 1
5. test2 : 0
6. test1 : 4
7. test1 : 3
8. test1 : 2
9. test1 : 1
10. test1 : 0
上述的代碼,第一個(gè)方法時(shí)用了同步代碼塊的方式進(jìn)行同步该溯,傳入的對(duì)象實(shí)例是this岛抄,表明是當(dāng)前對(duì)象,當(dāng)然狈茉,如果需要同步其他對(duì)象實(shí)例夫椭,也不可傳入其他對(duì)象的實(shí)例;第二個(gè)方法是修飾方法的方式進(jìn)行同步氯庆。因?yàn)榈谝粋€(gè)同步代碼塊傳入的this蹭秋,所以?xún)蓚€(gè)同步代碼所需要獲得的對(duì)象鎖都是同一個(gè)對(duì)象鎖,下面main方法時(shí)分別開(kāi)啟兩個(gè)線(xiàn)程堤撵,分別調(diào)用test1和test2方法仁讨,那么兩個(gè)線(xiàn)程都需要獲得該對(duì)象鎖,另一個(gè)線(xiàn)程必須等待实昨。上面也給出了運(yùn)行的結(jié)果可以看到:直到test2線(xiàn)程執(zhí)行完畢洞豁,釋放掉鎖,test1線(xiàn)程才開(kāi)始執(zhí)行荒给。(可能這個(gè)結(jié)果有人會(huì)有疑問(wèn)丈挟,代碼里面明明是先開(kāi)啟test1線(xiàn)程,為什么先執(zhí)行的是test2呢志电?這是因?yàn)閖ava編譯器在編譯成字節(jié)碼的時(shí)候曙咽,會(huì)對(duì)代碼進(jìn)行一個(gè)重排序,也就是說(shuō)挑辆,編譯器會(huì)根據(jù)實(shí)際情況對(duì)代碼進(jìn)行一個(gè)合理的排序例朱,編譯前代碼寫(xiě)在前面,在編譯后的字節(jié)碼不一定排在前面鱼蝉,所以這種運(yùn)行結(jié)果是正常的茉继, 這里是題外話(huà),最主要是檢驗(yàn)synchronized的用法的正確性)
如果我們把test2方法的synchronized關(guān)鍵字去掉蚀乔,執(zhí)行結(jié)果會(huì)如何呢?
1. test1 : 4
2. test2 : 4
3. test2 : 3
4. test1 : 3
5. test1 : 2
6. test2 : 2
7. test2 : 1
8. test1 : 1
9. test2 : 0
10. test1 : 0
上面是執(zhí)行結(jié)果菲茬,我們可以看到吉挣,結(jié)果輸出是交替著進(jìn)行輸出的派撕,這是因?yàn)椋硞€(gè)線(xiàn)程得到了對(duì)象鎖睬魂,但是另一個(gè)線(xiàn)程還是可以訪(fǎng)問(wèn)沒(méi)有進(jìn)行同步的方法或者代碼终吼。進(jìn)行了同步的方法(加鎖方法)和沒(méi)有進(jìn)行同步的方法(普通方法)是互不影響的,一個(gè)線(xiàn)程進(jìn)入了同步方法氯哮,得到了對(duì)象鎖际跪,其他線(xiàn)程還是可以訪(fǎng)問(wèn)那些沒(méi)有同步的方法(普通方法)。這里涉及到內(nèi)置鎖的一個(gè)概念(此概念出自java并發(fā)編程實(shí)戰(zhàn)第二章):對(duì)象的內(nèi)置鎖和對(duì)象的狀態(tài)之間是沒(méi)有內(nèi)在的關(guān)聯(lián)的喉钢,雖然大多數(shù)類(lèi)都將內(nèi)置鎖用做一種有效的加鎖機(jī)制姆打,但對(duì)象的域并不一定通過(guò)內(nèi)置鎖來(lái)保護(hù)。當(dāng)獲取到與對(duì)象關(guān)聯(lián)的內(nèi)置鎖時(shí)肠虽,并不能阻止其他線(xiàn)程訪(fǎng)問(wèn)該對(duì)象幔戏,當(dāng)某個(gè)線(xiàn)程獲得對(duì)象的鎖之后,只能阻止其他線(xiàn)程獲得同一個(gè)鎖税课。之所以每個(gè)對(duì)象都有一個(gè)內(nèi)置鎖闲延,是為了免去顯式地創(chuàng)建鎖對(duì)象。
所以synchronized只是一個(gè)內(nèi)置鎖的加鎖機(jī)制韩玩,當(dāng)某個(gè)方法加上synchronized關(guān)鍵字后垒玲,就表明要獲得該內(nèi)置鎖才能執(zhí)行,并不能阻止其他線(xiàn)程訪(fǎng)問(wèn)不需要獲得該內(nèi)置鎖的方法找颓。
類(lèi)鎖的修飾(靜態(tài))方法和代碼塊:
public class TestSynchronized {
public void test1() {
synchronized (TestSynchronized.class) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public static synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt2.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
TestSynchronized.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
運(yùn)行結(jié)果:
1.test1 : 4
2.test1 : 3
3.test1 : 2
4.test1 : 1
5.test1 : 0
6.test2 : 4
7.test2 : 3
8.test2 : 2
9.test2 : 1
10.test2 : 0
其實(shí)合愈,類(lèi)鎖修飾方法和代碼塊的效果和對(duì)象鎖是一樣的,因?yàn)轭?lèi)鎖只是一個(gè)抽象出來(lái)的概念叮雳,只是為了區(qū)別靜態(tài)方法的特點(diǎn)想暗,因?yàn)殪o態(tài)方法是所有對(duì)象實(shí)例共用的,所以對(duì)應(yīng)著synchronized修飾的靜態(tài)方法的鎖也是唯一的帘不,所以抽象出來(lái)個(gè)類(lèi)鎖说莫。其實(shí)這里的重點(diǎn)在下面這塊代碼,synchronized同時(shí)修飾靜態(tài)和非靜態(tài)方法:
public class TestSynchronized {
public synchronized void test1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt2.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
TestSynchronized.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
運(yùn)行結(jié)果:
1.test1 : 4
2.test2 : 4
3.test1 : 3
4.test2 : 3
5.test2 : 2
6.test1 : 2
7.test2 : 1
8.test1 : 1
9.test1 : 0
10.test2 : 0
上面代碼synchronized同時(shí)修飾靜態(tài)方法和實(shí)例方法寞焙,但是運(yùn)行結(jié)果是交替進(jìn)行的储狭,這證明了類(lèi)鎖和對(duì)象鎖是兩個(gè)不一樣的鎖,控制著不同的區(qū)域捣郊,它們是互不干擾的辽狈。同樣,線(xiàn)程獲得對(duì)象鎖的同時(shí)呛牲,也可以獲得該類(lèi)鎖刮萌,即同時(shí)獲得兩個(gè)鎖,這是允許的娘扩。
到這里着茸,對(duì)synchronized的用法已經(jīng)有了一定的了解壮锻。這時(shí)有一個(gè)疑問(wèn),既然有了synchronized修飾方法的同步方式涮阔,為什么還需要synchronized修飾同步代碼塊的方式呢猜绣?而這個(gè)問(wèn)題也是synchronized的缺陷所在
synchronized的缺陷:當(dāng)某個(gè)線(xiàn)程進(jìn)入同步方法獲得對(duì)象鎖,那么其他線(xiàn)程訪(fǎng)問(wèn)這里對(duì)象的同步方法時(shí)敬特,必須等待或者阻塞掰邢,這對(duì)高并發(fā)的系統(tǒng)是致命的,這很容易導(dǎo)致系統(tǒng)的崩潰伟阔。如果某個(gè)線(xiàn)程在同步方法里面發(fā)生了死循環(huán)辣之,那么它就永遠(yuǎn)不會(huì)釋放這個(gè)對(duì)象鎖,那么其他線(xiàn)程就要永遠(yuǎn)的等待减俏。這是一個(gè)致命的問(wèn)題召烂。
當(dāng)然同步方法和同步代碼塊都會(huì)有這樣的缺陷,只要用了synchronized關(guān)鍵字就會(huì)有這樣的風(fēng)險(xiǎn)和缺陷娃承。既然避免不了這種缺陷奏夫,那么就應(yīng)該將風(fēng)險(xiǎn)降到最低。這也是同步代碼塊在某種情況下要優(yōu)于同步方法的方面历筝。例如在某個(gè)類(lèi)的方法里面:這個(gè)類(lèi)里面聲明了一個(gè)對(duì)象實(shí)例酗昼,SynObject so=new SynObject();在某個(gè)方法里面調(diào)用了這個(gè)實(shí)例的方法so.testsy();但是調(diào)用這個(gè)方法需要進(jìn)行同步梳猪,不能同時(shí)有多個(gè)線(xiàn)程同時(shí)執(zhí)行調(diào)用這個(gè)方法麻削。
這時(shí)如果直接用synchronized修飾調(diào)用了so.testsy();代碼的方法,那么當(dāng)某個(gè)線(xiàn)程進(jìn)入了這個(gè)方法之后春弥,這個(gè)對(duì)象其他同步方法都不能給其他線(xiàn)程訪(fǎng)問(wèn)了呛哟。假如這個(gè)方法需要執(zhí)行的時(shí)間很長(zhǎng),那么其他線(xiàn)程會(huì)一直阻塞匿沛,影響到系統(tǒng)的性能扫责。
如果這時(shí)用synchronized來(lái)修飾代碼塊:synchronized(so){so.testsy();},那么這個(gè)方法加鎖的對(duì)象是so這個(gè)對(duì)象逃呼,跟執(zhí)行這行代碼的對(duì)象沒(méi)有關(guān)系鳖孤,當(dāng)一個(gè)線(xiàn)程執(zhí)行這個(gè)方法時(shí),這對(duì)其他同步方法時(shí)沒(méi)有影響的抡笼,因?yàn)樗麄兂钟械逆i都完全不一樣苏揣。
不過(guò)這里還有一種特例,就是上面演示的第一個(gè)例子推姻,對(duì)象鎖synchronized同時(shí)修飾方法和代碼塊平匈,這時(shí)也可以體現(xiàn)到同步代碼塊的優(yōu)越性,如果test1方法同步代碼塊后面有非常多沒(méi)有同步的代碼,而且有一個(gè)100000的循環(huán)吐葱,這導(dǎo)致test1方法會(huì)執(zhí)行時(shí)間非常長(zhǎng)街望,那么如果直接用synchronized修飾方法,那么在方法沒(méi)執(zhí)行完之前弟跑,其他線(xiàn)程是不可以訪(fǎng)問(wèn)test2方法的,但是如果用了同步代碼塊防症,那么當(dāng)退出代碼塊時(shí)就已經(jīng)釋放了對(duì)象鎖孟辑,當(dāng)線(xiàn)程還在執(zhí)行test1的那個(gè)100000的循環(huán)時(shí),其他線(xiàn)程就已經(jīng)可以訪(fǎng)問(wèn)test2方法了蔫敲。這就讓阻塞的機(jī)會(huì)或者線(xiàn)程更少饲嗽。讓系統(tǒng)的性能更優(yōu)越。
一個(gè)類(lèi)的對(duì)象鎖和另一個(gè)類(lèi)的對(duì)象鎖是沒(méi)有關(guān)聯(lián)的奈嘿,當(dāng)一個(gè)線(xiàn)程獲得A類(lèi)的對(duì)象鎖時(shí)貌虾,它同時(shí)也可以獲得B類(lèi)的對(duì)象鎖。
可能上面只有理論和代碼裙犹,對(duì)剛接觸的人比較難理解尽狠,下面舉一個(gè)例子,
打個(gè)比方:一個(gè)object就像一個(gè)大房子叶圃,大門(mén)永遠(yuǎn)打開(kāi)袄膏。房子里有 很多房間(也就是方法)。
這些房間有上鎖的(synchronized方法)掺冠, 和不上鎖之分(普通方法)沉馆。房門(mén)口放著一把鑰匙(key),這把鑰匙可以打開(kāi)所有上鎖的房間德崭。
另外我把所有想調(diào)用該對(duì)象方法的線(xiàn)程比喻成想進(jìn)入這房子某個(gè) 房間的人斥黑。所有的東西就這么多了,下面我們看看這些東西之間如何作用的眉厨。
在此我們先來(lái)明確一下我們的前提條件锌奴。該對(duì)象至少有一個(gè)synchronized方法,否則這個(gè)key還有啥意義缺猛。當(dāng)然也就不會(huì)有我們的這個(gè)主題了缨叫。
一個(gè)人想進(jìn)入某間上了鎖的房間,他來(lái)到房子門(mén)口荔燎,看見(jiàn)鑰匙在那兒(說(shuō)明暫時(shí)還沒(méi)有其他人要使用上鎖的 房間)耻姥。于是他走上去拿到了鑰匙,并且按照自己 的計(jì)劃使用那些房間有咨。注意一點(diǎn)琐簇,他每次使用完一次上鎖的房間后會(huì)馬上把鑰匙還回去。即使他要連續(xù)使用兩間上鎖的房間,中間他也要把鑰匙還回去婉商,再取回來(lái)似忧。
因此,普通情況下鑰匙的使用原則是:“隨用隨借丈秩,用完即還盯捌。”
這時(shí)其他人可以不受限制的使用那些不上鎖的房間蘑秽,一個(gè)人用一間可以饺著,兩個(gè)人用一間也可以,沒(méi)限制肠牲。但是如果當(dāng)某個(gè)人想要進(jìn)入上鎖的房間幼衰,他就要跑到大門(mén)口去看看了。有鑰匙當(dāng)然拿了就走缀雳,沒(méi)有的話(huà)渡嚣,就只能等了。
要是很多人在等這把鑰匙肥印,等鑰匙還回來(lái)以后识椰,誰(shuí)會(huì)優(yōu)先得到鑰匙?Not guaranteed竖独。象前面例子里那個(gè)想連續(xù)使用兩個(gè)上鎖房間的家伙裤唠,他中間還鑰匙的時(shí)候如果還有其他人在等鑰匙,那么沒(méi)有任何保證這家伙能再次拿到莹痢。 (JAVA規(guī)范在很多地方都明確說(shuō)明不保證种蘸,像Thread.sleep()休息后多久會(huì)返回運(yùn)行,相同優(yōu)先權(quán)的線(xiàn)程那個(gè)首先被執(zhí)行竞膳,當(dāng)要訪(fǎng)問(wèn)對(duì)象的鎖被 釋放后處于等待池的多個(gè)線(xiàn)程哪個(gè)會(huì)優(yōu)先得到航瞭,等等。我想最終的決定權(quán)是在JVM坦辟,之所以不保證刊侯,就是因?yàn)镴VM在做出上述決定的時(shí)候,絕不是簡(jiǎn)簡(jiǎn)單單根據(jù) 一個(gè)條件來(lái)做出判斷锉走,而是根據(jù)很多條滨彻。而由于判斷條件太多,如果說(shuō)出來(lái)可能會(huì)影響JAVA的推廣挪蹭,也可能是因?yàn)橹R(shí)產(chǎn)權(quán)保護(hù)的原因吧亭饵。SUN給了個(gè)不保證 就混過(guò)去了。無(wú)可厚非梁厉。但我相信這些不確定辜羊,并非完全不確定。因?yàn)橛?jì)算機(jī)這東西本身就是按指令運(yùn)行的。即使看起來(lái)很隨機(jī)的現(xiàn)象八秃,其實(shí)都是有規(guī)律可尋碱妆。學(xué)過(guò) 計(jì)算機(jī)的都知道,計(jì)算機(jī)里隨機(jī)數(shù)的學(xué)名是偽隨機(jī)數(shù)昔驱,是人運(yùn)用一定的方法寫(xiě)出來(lái)的疹尾,看上去隨機(jī)罷了。另外舍悯,或許是因?yàn)橐肱拇_太費(fèi)事航棱,也沒(méi)多大意義,所 以不確定就不確定了吧萌衬。)
再來(lái)看看同步代碼塊。和同步方法有小小的不同它抱。
1.從尺寸上講秕豫,同步代碼塊比同步方法小。你可以把同步代碼塊看成是沒(méi)上鎖房間里的一塊用帶鎖的屏風(fēng)隔開(kāi)的空間观蓄。
2.同步代碼塊還可以人為的指定獲得某個(gè)其它對(duì)象的key混移。就像是指定用哪一把鑰匙才能開(kāi)這個(gè)屏風(fēng)的鎖,你可以用本房的鑰匙侮穿;你也可以指定用另一個(gè)房子的鑰匙才能開(kāi)歌径,這樣的話(huà),你要跑到另一棟房子那兒把那個(gè)鑰匙拿來(lái)亲茅,并用那個(gè)房子的鑰匙來(lái)打開(kāi)這個(gè)房子的帶鎖的屏風(fēng)回铛。
記住你獲得的那另一棟房子的鑰匙,并不影響其他人進(jìn)入那棟房子沒(méi)有鎖的房間克锣。
為什么要使用同步代碼塊呢茵肃?我想應(yīng)該是這樣的:首先對(duì)程序來(lái)講同步的部分很影響運(yùn)行效率,而一個(gè)方法通常是先創(chuàng)建一些局部變量袭祟,再對(duì)這些變量做一些 操作验残,如運(yùn)算,顯示等等巾乳;而同步所覆蓋的代碼越多您没,對(duì)效率的影響就越嚴(yán)重。因此我們通常盡量縮小其影響范圍胆绊。
如何做氨鹏?同步代碼塊。我們只把一個(gè)方法中該同 步的地方同步辑舷,比如運(yùn)算喻犁。
另外,同步代碼塊可以指定鑰匙這一特點(diǎn)有個(gè)額外的好處,是可以在一定時(shí)期內(nèi)霸占某個(gè)對(duì)象的key肢础。還記得前面說(shuō)過(guò)普通情況下鑰匙的使用原則嗎』顾ǎ現(xiàn)在不是普通情況了。你所取得的那把鑰匙不是永遠(yuǎn)不還传轰,而是在退出同步代碼塊時(shí)才還剩盒。
還用前面那個(gè)想連續(xù)用兩個(gè)上鎖房間的家伙打比方。怎樣才能在用完一間以后慨蛙,繼續(xù)使用另一間呢辽聊。用同步代碼塊吧。先創(chuàng)建另外一個(gè)線(xiàn)程期贫,做一個(gè)同步代碼 塊跟匆,把那個(gè)代碼塊的鎖指向這個(gè)房子的鑰匙。然后啟動(dòng)那個(gè)線(xiàn)程通砍。只要你能在進(jìn)入那個(gè)代碼塊時(shí)抓到這房子的鑰匙玛臂,你就可以一直保留到退出那個(gè)代碼塊。也就是說(shuō) 你甚至可以對(duì)本房?jī)?nèi)所有上鎖的房間遍歷封孙,甚至再sleep(10601000)迹冤,而房門(mén)口卻還有1000個(gè)線(xiàn)程在等這把鑰匙呢。很過(guò)癮吧虎忌。
synchronized作用于靜態(tài)方法和非靜態(tài)方法的區(qū)別:
非靜態(tài)方法:
給對(duì)象加鎖(可以理解為給這個(gè)對(duì)象的內(nèi)存上鎖,注意 只是這塊內(nèi)存,其他同類(lèi)對(duì)象都會(huì)有各自的內(nèi)存鎖),這時(shí)候在其他一個(gè)以上線(xiàn)程中執(zhí)行該對(duì)象的這個(gè)同步方法(注意:是該對(duì)象)就會(huì)產(chǎn)生互斥靜態(tài)方法:
相當(dāng)于在類(lèi)上加鎖(*.class 位于代碼區(qū),靜態(tài)方法位于靜態(tài)區(qū)域,這個(gè)類(lèi)產(chǎn)生的對(duì)象公用這個(gè)靜態(tài)方法,所以這塊內(nèi)存泡徙,N個(gè)對(duì)象來(lái)競(jìng)爭(zhēng)), 這時(shí)候,只要是這個(gè)類(lèi)產(chǎn)生的對(duì)象,在調(diào)用這個(gè)靜態(tài)方法時(shí)都會(huì)產(chǎn)生互斥