Java多線程 synchronized修飾的用法的淺談

看到網上不少資料都講解synchronized的用法詳解,確實有不少的知識點,但初學者可能看的比較頭暈,這裏淺談下很重要的synchronized修飾普通方法和修飾靜態方法,也是在實際開發中用的比較多的。java

這裏先說synchronized修飾普通方法,修飾代碼塊和修飾靜態方法的最大特色:安全

修飾普通方法,修飾代碼塊:只針對調用它的對象起做用。this

修飾靜態方法:針對該類的全部對象都起做用。線程

直接上代碼:code

​
public class SyncTest {

     public void test1(){
            synchronized (this){
                for (int i = 0; i < 10; i++) {
                    log.info("test1 - {}",i);
                }
            }
     }
     public synchronized void test2(){
         for (int i = 0; i < 10; i++) {
             log.info("test2 - {}",i);
         }

     }
    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();      
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() ->{
            syncTest1.test1();
        });
        executorService.execute(() ->{
            syncTest1.test1();
        });
    }
}

​

輸出結果:對象

能夠看出,兩個線程很好的保持了同步,達到了線程安全的效果,blog

出現這個的緣由是:在test1方法中,咱們使用同一個對象調用它,因此每一個線程都要依次得到該對象的鎖才能執行,這裏注意的是,起做用的是該對象(同一個),下面調用test2方法結果也一致,由於執行代碼都在synchronized裏被修飾了。開發

可是若是咱們新增長一個對象,分別調用本身的test1方法,以下:同步

SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() ->{
            syncTest1.test2();
        });
        executorService.execute(() ->{
            syncTest2.test2();
        });

結果:
class

能夠看到,結果是線程不一樣步的,這是由於用synchronized修飾的只對當前對象起做用,而對其餘對象的synchronized所針對的對象是不干擾的。

下面來看調用靜態方法會出現什麼結果:

public class SyncTest {

     public void test1(){
            synchronized (this){
                for (int i = 0; i < 10; i++) {
                    log.info("test1 - {}",i);
                }
            }
     }

     public synchronized static void test2(){ //改成靜態方法
         for (int i = 0; i < 10; i++) {
             log.info("test2 - {}",i);
         }

     }

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() ->{
            syncTest1.test2();
        });
        executorService.execute(() ->{
            syncTest2.test2();
        });
    }
}

咱們將test2方法改成靜態方法,也是建立兩個對象,調用本身的test2方法,結果以下:

能夠看到,線程也是同步的,這是由於synchronized修飾靜態方法(修飾類),起做用的對象是屬於整個類的,就是說只要是該類的對象在調用該類被synchronized修飾的方法時都要保持線程同步。

若是有錯誤的地方,請歡迎指正!

相關文章
相關標籤/搜索