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


 

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互斥

method1 begin at:1381584063557
method1 end at:1381584069557
method2 running
method2 running
Thread1 still alive
method2 running
Thread1 still alive
method2 running
Thread1 still alive
method2 running
method2 running
method2 running
method2 running
method2 running
method2 running
method2 running
method2 running

 

 
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM