1. 程式人生 > >synchronized對普通同步方法和對靜態方法的區別

synchronized對普通同步方法和對靜態方法的區別

synchronized是一個重量級鎖,我們都知道該關鍵字鎖住的是物件而不是程式碼本身,那麼對於靜態方法和同步方法有什麼不同呢,通過如下程式碼進行測試
public class SynchronizedTest {

    private static int num;

    private synchronized void test(String param){
        if(StringUtils.equals(param,"a")){
            num = 100;
            System.out.println("set " + param + " num over");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            num = 200;
            System.out.println("set " + param + " num over");
        }
        System.out.println("i am : " + param + "; num = " + num);
    }

    public static void main(String[] args){
        SynchronizedTest s1 = new SynchronizedTest();
        SynchronizedTest s2 = new SynchronizedTest();

        new Thread(new Runnable() {
            @Override
            public void run() {
                s1.test("a");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                s2.test("b");
            }
        }).start();
    }
}

輸出結果為:


set a num over
set b num over
i am : b; num = 200
i am : a; num = 200

Process finished with exit code 0

我們可以看出兩個不同的物件s1和s2並沒有互斥,因為這裡synchronized是分別持有兩個物件的鎖。如果要想m1,m2兩個物件競爭同一個鎖,則需要在method01()上加上static修飾,如下:

public class SynchronizedTest {

    private static int num;

    private synchronized static void test(String param){
        if(StringUtils.equals(param,"a")){
            num = 100;
            System.out.println("set " + param + " num over");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            num = 200;
            System.out.println("set " + param + " num over");
        }
        System.out.println("i am : " + param + "; num = " + num);
    }

    public static void main(String[] args){
        SynchronizedTest s1 = new SynchronizedTest();
        SynchronizedTest s2 = new SynchronizedTest();

        new Thread(new Runnable() {
            @Override
            public void run() {
                s1.test("a");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                s2.test("b");
            }
        }).start();
    }
}

執行結果如下:

set a num over
i am : a; num = 100
set b num over
i am : b; num = 200

Process finished with exit code 0

synchronized修飾不加static的方法,鎖是加在單個物件上,不同的物件沒有競爭關係;修飾加了static的方法,鎖是載入類上,這個類所有的物件競爭一把鎖.