1. 語法不同。
創(chuàng)新互聯(lián)公司于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元澗西做網(wǎng)站,已為上家服務(wù),為澗西各地企業(yè)和個人服務(wù),聯(lián)系電話:18982081108
2. 同步塊需要注明鎖定對象,同步方法默認(rèn)鎖定this。
3. 在靜態(tài)方法中,都是默認(rèn)鎖定類對象。
4. 在考慮性能方面,最好使用同步塊來減少鎖定范圍提高并發(fā)效率。
synchronized(這里的對象你看成一道門) {
這里是一個人進(jìn)來了,把門反鎖了
需要同步操作的代碼
這里是里面的人事情做完了,出去了,門開著其他人可以進(jìn)了
}
至于怎么鎖的,這是java和jvm的規(guī)定和實(shí)現(xiàn)細(xì)節(jié),作為普通程序員沒必要深入那么多。
在Java語言中,每一個對象有一把鎖。線程可以使用synchronized關(guān)鍵字來獲取對象上的鎖。synchronized關(guān)鍵字可應(yīng)用在方法級別(粗粒度鎖)或者是代碼塊級別(細(xì)粒度鎖)。
問題的由來:
看到這樣一個面試題:
?
1
2
3
4
5
6
//下列兩個方法有什么區(qū)別
public synchronized void method1(){}
public void method2(){
synchronized (obj){}
}
synchronized用于解決同步問題,當(dāng)有多條線程同時訪問共享數(shù)據(jù)時,如果進(jìn)行同步,就會發(fā)生錯誤,Java提供的解決方案是:只要將操作共享數(shù)據(jù)的語句在某一時段讓一個線程執(zhí)行完,在執(zhí)行過程中,其他線程不能進(jìn)來執(zhí)行可以。解決這個問題。這里在用synchronized時會有兩種方式,一種是上面的同步方法,即用synchronized來修飾方法,另一種是提供的同步代碼塊。
這里總感覺怪怪的,這兩種方法有什么區(qū)別呢,基礎(chǔ)學(xué)得不好,于是就動手做了個簡單的測試,代碼如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SynObj {
public synchronized void methodA() {
System.out.println("methodA.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB() {
synchronized(this) {
System.out.pritntln("methodB.....");
}
}
public void methodC() {
String str = "sss";
synchronized (str) {
System.out.println( "methodC.....");
}
}
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TestSyn {
public static void main(String[] args) {
final SynObj obj = new SynObj();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
obj.methodA();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
obj.methodB();
}
});
t2.start();
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
obj.methodC();
}
});
t3.start();
}
}
這段小代碼片段打印結(jié)果如下:
?
1
2
3
4
methodA.....
methodC.....
//methodB會隔一段時間才會打印出來
methodB.....
這段代碼的打印結(jié)果是,methodA…..methodC…..會很快打印出來,methodB…..會隔一段時間才打印出來,那么methodB為什么不能像methodC那樣很快被調(diào)用呢?
在啟動線程1調(diào)用方法A后,接著會讓線程1休眠5秒鐘,這時會調(diào)用方法C,注意到方法C這里用synchronized進(jìn)行加鎖,這里鎖的對象是str這個字符串對象。但是方法B則不同,是用當(dāng)前對象this進(jìn)行加鎖,注意到方法A直接在方法上加synchronized,這個加鎖的對象是什么呢?顯然,這兩個方法用的是一把鎖。
*由這樣的結(jié)果,我們就知道這樣同步方法是用什么加鎖的了,由于線程1在休眠,這時鎖還沒釋放,導(dǎo)致線程2只有在5秒之后才能調(diào)用方法B,由此,可知兩種加鎖機(jī)制用的是同一個鎖對象,即當(dāng)前對象。
另外,同步方法直接在方法上加synchronized實(shí)現(xiàn)加鎖,同步代碼塊則在方法內(nèi)部加鎖,很明顯,同步方法鎖的范圍比較大,而同步代碼塊范圍要小點(diǎn),一般同步的范圍越大,性能就越差,一般需要加鎖進(jìn)行同步的時候,肯定是范圍越小越好,這樣性能更好。