前言
看到一個關(guān)于syncronized的題蠢箩,回想了一下syncronized的用法,感覺好多又忘記了事甜,這次把整個syncronized的用法總一次完整的總結(jié)谬泌,以后面試的時候應(yīng)該沒啥問題了。全篇如有不正確逻谦,請指出呵萨,謝謝,本文案例都是測試通過跨跨。
synchronized是Java中的關(guān)鍵字潮峦,是一種同步鎖。它修飾的對象有以下幾種:
- 修飾一個代碼塊勇婴,被修飾的代碼塊稱為同步語句塊忱嘹,其作用的范圍是大括號{}括起來的代碼,作用的對象是調(diào)用這個代碼塊的對象耕渴;
- 修飾一個方法拘悦,被修飾的方法稱為同步方法,其作用的范圍是整個方法橱脸,作用的對象是調(diào)用這個方法的對象础米;
- 修改一個靜態(tài)的方法,其作用的范圍是整個靜態(tài)方法添诉,作用的對象是這個類的所有對象屁桑;
- 修改一個類,其作用的范圍是synchronized后面括號括起來的部分栏赴,作用主的對象是這個類的所有對象蘑斧。
修飾代碼塊,簡單寫法就是
syncrionzed(this){
...
}
this是什么?
這里的this是指對象了還是指實例了竖瘾?很多人都應(yīng)該考慮過這個問題沟突,下面通過代碼解釋this到底是指什么
package com.company.syncronized;
/**
* Created by wxwall on 2017/6/6.
*/
class SyncronizedDemo implements Runnable{
public static void main(String[] args) {
SyncronizedDemo demo = new SyncronizedDemo();
System.out.println(demo.toString());
Thread t = new Thread(demo);
Thread t1 = new Thread(demo);
t.start();
t1.start();
}
@Override
public void run() {
System.out.println(this.toString());
}
}
輸出結(jié)果:
com.company.syncronized.SyncronizedDemo@1a758cb
com.company.syncronized.SyncronizedDemo@1a758cb
com.company.syncronized.SyncronizedDemo@1a758cb
這里可以看出this是指這個對象的實例,這點很重要捕传,因為synchronized括號里具體是指對象還是指實例惠拭,直接影響代碼結(jié)果。
單個實例庸论,一個時間內(nèi)只能有一個線程得到執(zhí)行
當(dāng)線程進(jìn)入synchronized代碼塊時求橄,其他獲得this這個實例的所有線程都是MONITOR狀態(tài),只能等到Thread-0程序走出代碼塊時葡公,釋放鎖后罐农,其他線程通過CPU調(diào)試分配鎖資源才能繼續(xù)執(zhí)行,這點依賴系統(tǒng)催什,程序是無法控制的涵亏。
多個實例,代碼塊將失效,一個時間內(nèi)有多個線程得到執(zhí)行
執(zhí)行結(jié)果會出現(xiàn)如下:
com.company.syncronized.SyncronizedDemo@1ff7a1e
com.company.syncronized.SyncronizedDemo@105738
Thread-0
Thread-1
這個時候如果想有多個實例蒲凶,又有多個線程想要執(zhí)行這個同步代碼塊怎么辦了气筋,這個時候,就要把synchronized(this)里的this對象換掉旋圆,換成對象宠默。
這里,如果換成類對象灵巧,這個代碼塊就無論有多少個實例搀矫,只要有線程來,就得一個一個來刻肄,所以瓤球,一開始就分清楚什么是括號里的加鎖的是對象還是加鎖實例,是不同的敏弃。
是不是方法體上加了synchronized就會在同一個時間只有一個線程執(zhí)行卦羡?
看下面的代碼,是不是沒有在同一個時間只有一個線程執(zhí)行
原因是兩個線程都new出來了個Test對象麦到,兩個線程其實是分別執(zhí)行自己的實例咸这,所以要避免這種問題出現(xiàn)時检眯,最好打印出來this關(guān)鍵字到底是指哪個對象虚汛。
Thread-0
Thread-1
com.company.syncronized.Test@15212bc
com.company.syncronized.Test@86fe26
這個時候痛垛,如果把要同步的對象改成共享變量就會按我們預(yù)定的想法走,結(jié)果如下
Thread-0
com.company.syncronized.Test@1bfc93a
Thread-1
com.company.syncronized.Test@1bfc93a
static synchronized 與synchronized 區(qū)別
如果要用文字說區(qū)別步清,那就是synchronized鎖對象問題要门,如果synchronized鎖的是對象,而不是實例廓啊,那與 static synchronized用法一樣欢搜,下面看例子說明
package com.company.syncronized;
/**
* Created by wxwall on 2017/6/6.
*/
class SyncronizedDemo implements Runnable{
public static void main(String[] args) {
SyncronizedDemo demo = new SyncronizedDemo();
Thread t = new Thread(demo);
Thread t1 = new Thread(demo);
t.start();
t1.start();
}
@Override
public void run() {
synchronized (Test.class){
Test.bb();
}
}
}
class Test {
public static void bb(){
System.out.println(Thread.currentThread().getName());
}
}
等同于
package com.company.syncronized;
/**
* Created by wxwall on 2017/6/6.
*/
class SyncronizedDemo implements Runnable{
public static void main(String[] args) {
SyncronizedDemo demo = new SyncronizedDemo();
Thread t = new Thread(demo);
Thread t1 = new Thread(demo);
t.start();
t1.start();
}
@Override
public void run() {
Test.bb();
}
}
class Test {
public static synchronized void bb(){
System.out.println(Thread.currentThread().getName());
}
}
所以,理解synchronized 最主要的點就是鎖的對象是哪個了谴轮。
鎖住對象了炒瘟,其他線程能不能進(jìn)入其他方法了?看代碼
我們發(fā)現(xiàn)第步,如果對象加鎖了疮装,其他線程是不可以進(jìn)入這個對象的其他加了synchronized 關(guān)鍵字的方法了。但如果其他方法沒加synchronized粘都,是可以進(jìn)入的廓推。
總結(jié)
關(guān)于synchronized介紹的文章已經(jīng)很多,本文是自己分析synchronized的一些見解翩隧,也是為了完善自己關(guān)于java基礎(chǔ)篇系列的補(bǔ)充樊展,希望我用圖解調(diào)試的方法解釋問題相比直接上代碼,然后對比輸出結(jié)果來得更加簡單容易點堆生,如果能幫助到您专缠,那就很開心了。