1. 程式人生 > >synchronized修飾普通方法,修飾靜態方法,修飾代碼塊,修飾線程run方法 比較

synchronized修飾普通方法,修飾靜態方法,修飾代碼塊,修飾線程run方法 比較

共享數據 比較 art text run best 初始 一個 lol

synchronized用於多線程設計,有了synchronized關鍵字,多線程程序的運行結果將變得可以控制。synchronized關鍵字用於保護共享數據。

synchronized實現同步的機制:synchronized依靠"鎖"機制進行多線程同步,"鎖"有2種,一種是對象鎖,一種是類鎖

1.依靠對象鎖鎖定

初始化一個對象時,自動有一個對象鎖。synchronized {普通方法}依靠對象鎖工作,多線程訪問synchronized方法,一旦某個進程搶得鎖之後,其他的進程只有排隊對待。


synchronized {普通方法}依靠對象鎖工作,多線程訪問synchronized方法,一旦某個進程搶得鎖之後,其他的進程只有排隊對待。 synchronized void method{}功能上,等效於 void method{ synchronized(this) {     ... } } 通過代碼看比較清楚:
public class TestSynchronized {
    public synchronized void method1() throws InterruptedException {
        System.out.println("method1 begin at:" + System.currentTimeMillis());
        Thread.sleep(6000);
        System.out.println("method1 end at:" + System.currentTimeMillis());
    }
    public synchronized void method2() throws InterruptedException {
        while(true) {
            System.out.println("method2 running");
            Thread.sleep(200);
        }
    }
    static TestSychronized instance = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance.method1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for(int i=1; i<4; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread1 still alive");
                }                    
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread1.start();
        thread2.start();    
        
    }
}

 運行結果:thread2一直等到thread1中的method1執行完了之後才執行method2,說明method1和method2互斥

synchronized {修飾代碼塊}的作用不僅於此,synchronized void method{}整個函數加上synchronized塊,效率並不好。在函數內部,可能我們需要同步的只是小部分共享數據,其他數據,可以自由訪問,這時候我們可以用 synchronized(表達式){//語句}更加精確的控制
  • 2.synchronized {static方法}此代碼塊等效於
void method{ synchronized(Obl.class) } } 使用該類的類對象的鎖定去做線程的共享互斥.
package com.free4lab.lol;

public class TestSychronized {
    public synchronized static void method1() throws InterruptedException {
        System.out.println("method1 begin at:" + System.currentTimeMillis());
        Thread.sleep(6000);
        System.out.println("method1 end at:" + System.currentTimeMillis());
    }
    public synchronized static void method2() throws InterruptedException {
        while(true) {
            System.out.println("method2 running");
            Thread.sleep(200);
        }
    }
    static TestSychronized instance1 = new TestSychronized();
    static TestSychronized instance2 = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance1.method1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for(int i=1; i<4; i++) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread1 still alive");
                }                    
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance2.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread1.start();
        thread2.start();    
        
    }
}

輸出效果也是method1和method2互斥

  • 3.synchronized {run方法}run方法的鎖定.
這個舉例比較好說
package com.free4lab.lol;

public class TestSychronized {
    static TestSychronized instance = new TestSychronized();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
                public synchronized void run() {
                    
                    for(int i=1; i<4; i++) {
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("Thread1 still alive, " + i);
                    }                    
                }
        });
        new Thread(thread1).start();
        new Thread(thread1).start();
    }
}

如果加了synchronized當前線程取完所有數據後,才會釋放鎖,輸出結果是有序的

Thread1 still alive, 1
Thread1 still alive, 2
Thread1 still alive, 3
Thread1 still alive, 1
Thread1 still alive, 2
Thread1 still alive, 3

  

 

synchronized修飾普通方法,修飾靜態方法,修飾代碼塊,修飾線程run方法 比較