synchronized簡(jiǎn)介
synchronized方法控制對(duì)類對(duì)象方法的訪問(wèn)幔睬,每個(gè)類對(duì)象都對(duì)應(yīng)一把鎖歇终,每個(gè)synchronized 方法都必須獲得該方法所屬對(duì)象的鎖方能執(zhí)行惰赋,否則所屬線程阻塞邑狸,方法一旦執(zhí)行坪郭,就獨(dú)占該對(duì)象鎖赊颠,直到從該方法返回時(shí)才將鎖釋放,此后被阻塞的線程方能獲得該鎖瑰剃,重新進(jìn)入可執(zhí)行狀態(tài)齿诉。這種機(jī)制確保了同一時(shí)刻對(duì)于每一個(gè)對(duì)象實(shí)例,其所有聲明為 synchronized 的實(shí)例函數(shù)中至多只有一個(gè)處于可執(zhí)行狀態(tài)晌姚,從而有效避免了類成員變量的訪問(wèn)沖突粤剧。注意,其它非synchronized的函數(shù)仍可被其它線程同時(shí)訪問(wèn)挥唠。
synchronized基本用法
- 修飾普通方法
public synchronized void inc(int i) {
i++;
}
- 修飾靜態(tài)方法
public static synchronized void inc(int i) {
i++;
}
- 修飾代碼塊
public void inc(int i) {
synchronized(this) {
i++;
}
}
哪個(gè)對(duì)象才是鎖抵恋??宝磨?
首先看兩個(gè)例子:
class Foo extends Thread {
private int val;
public Foo(int v) {
val = v;
}
public synchronized void printVal(int v) {
while (true) {
System.out.println(v);
}
}
public void run() {
printVal(val);
}
}
public class SyncTest {
public static void main(String args[]) {
Foo f1 = new Foo(1);
f1.start();
Foo f2 = new Foo(3);
f2.start();
}
}
//運(yùn)行結(jié)果:
1
1
3
3
.....//1和3循環(huán)出現(xiàn)
修改為:
class Foo extends Thread {
private int val;
public Foo(int v) {
val = v;
}
public void printVal(int v) {
synchronized(Foo.class) {
while(true)
System.out.println(v);
}
}
public void run() {
printVal(val);
}
}
//運(yùn)行結(jié)果:
1
1
1
......//1循環(huán)出現(xiàn)弧关,沒有出現(xiàn)3
總結(jié):同一時(shí)刻對(duì)于每一個(gè)對(duì)象實(shí)例,其所有聲明為 synchronized 的實(shí)例函數(shù)中至多只有一個(gè)處于可執(zhí)行狀態(tài)唤锉。第一個(gè)例子有兩個(gè)實(shí)例對(duì)象梯醒,所以他們都可以訪問(wèn)printVal方法;第二個(gè)例子只有一個(gè)類對(duì)象腌紧,所以只有一個(gè)實(shí)例可以訪問(wèn)printVal方法。
synchronized特點(diǎn)
- 可重入鎖
這個(gè)特性主要是針對(duì)當(dāng)前線程而言的畜隶,可重入即是自己可以再次獲得自己的內(nèi)部鎖壁肋,在嘗試獲取對(duì)象鎖時(shí),如果當(dāng)前線程已經(jīng)擁有了此對(duì)象的鎖籽慢,則把鎖的計(jì)數(shù)器加一浸遗,在釋放鎖時(shí)則對(duì)應(yīng)地減一,當(dāng)鎖計(jì)數(shù)器為0時(shí)表示鎖完全被釋放箱亿,此時(shí)其他線程可對(duì)其加鎖跛锌。可重入可以避免死鎖(線程自己鎖死自己)届惋。
- 非公平鎖
非公平主要表現(xiàn)在獲取鎖的行為上髓帽,并非是按照申請(qǐng)鎖的時(shí)間前后給等待線程分配鎖的,每當(dāng)鎖被釋放后脑豹,任何一個(gè)線程都有機(jī)會(huì)競(jìng)爭(zhēng)到鎖郑藏,這樣做的目的是為了提高執(zhí)行性能,當(dāng)然也會(huì)產(chǎn)生線程饑餓現(xiàn)象瘩欺。
- 不可中斷性
在所有等待的線程中必盖,你們唯一能做的就是等拌牲,而實(shí)際情況可能是有些任務(wù)等了足夠久了,我要取消此任務(wù)去干別的事情歌粥,此時(shí)synchronized是無(wú)法幫你實(shí)現(xiàn)的塌忽,它把所有實(shí)現(xiàn)機(jī)制都交給了JVM,提供了方便的同時(shí)也體現(xiàn)出了自己的局限性失驶。
- 只能綁定一個(gè)條件
鎖對(duì)象的wait()和notify()或notifyAll()方法可以實(shí)現(xiàn)一個(gè)隱含的條件土居,如果要和多于一個(gè)條件關(guān)聯(lián)時(shí),只能再加一個(gè)額外的鎖突勇。
- 主動(dòng)釋放鎖
線程進(jìn)入同步代碼塊或方法的時(shí)候會(huì)自動(dòng)獲得該鎖装盯,在退出同步代碼塊或方法時(shí)會(huì)釋放該鎖。