synchronized的對象鎖和類鎖的區別

synchronized可以鎖對象,代碼塊,類對象 ,那麼他們用起來會有區別嗎,這裏我們用實際代碼來探究下

package com.example.hxk.thread.synchroized;

public class SyncTest1 {

    // synchronized修飾非靜態方法
    public synchronized void test1() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // synchronized代碼塊
    public void test2() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        SyncTest1 t1 = new SyncTest1();

        new Thread(new Runnable() {
            @Override
            public void run() {
                t1.test1();
            }
        }, "thread1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                t1.test2();
            }
        }, "thread2").start();
    }
}

運行結果:

thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4

這裏thread2會等thread1運行完成纔會開始運行,說明thread1和thread2請求的是同一把鎖,也就說明了 synchronized代碼塊鎖當前對象和鎖非靜態方法,他們的效果是一樣的, 鎖的都是當前對象。

然後我們再來看看類鎖,修改代碼如下

package com.example.hxk.thread.synchroized;

public class SyncTest1 {

    // 修飾靜態方法
    public static synchronized void test1() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 修飾類對象
    public void test2() {
        synchronized (SyncTest1.class) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        SyncTest1 t1 = new SyncTest1();

        new Thread(new Runnable() {
            @Override
            public void run() {
                SyncTest1.test1();
            }
        }, "thread1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                t1.test2();
            }
        }, "thread2").start();
    }
}

運行結果:

thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4

這裏可以看到thread2也是被thread1阻塞,所以他們持有的是同一把鎖,也就說明synchronized修飾靜態方法和鎖類對象,他們的效果是一樣的。 接下來我們同時用類鎖和對象鎖試試,代碼如下

package com.example.hxk.thread.synchroized;

public class SyncTest1 {

    // 修飾靜態方法
    public static synchronized void test1() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 修飾類對象
    public synchronized void test2() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SyncTest1 t1 = new SyncTest1();

        new Thread(new Runnable() {
            @Override
            public void run() {
                SyncTest1.test1();
            }
        }, "thread1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                t1.test2();
            }
        }, "thread2").start();
    }
}

運行結果:

thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4

運行結果是交替進行的,說明對象鎖和類鎖鎖的不是同一個鎖,他們是兩個鎖,互不影響

總結:
1,synchronized修飾在非靜態方法上和synchronized(this){} 同步代碼塊效果是一樣的

2,synchronized修飾在靜態方法上和 synchronized (SyncTest1.class) {} 同步代碼塊效果是一樣的

3,synchronized修飾在非靜態方法表示鎖的是當前對象,修飾靜態方法表示鎖的是類對象(一個類在jvm中只有一個class對象)

來源:https://www.tuicool.com/articles/e6j2YnR

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章