美文网首页面试题
synchronized的对象锁和类锁的区别

synchronized的对象锁和类锁的区别

作者: Java柱柱 | 来源:发表于2020-12-03 21:46 被阅读0次

    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

    相关文章

      网友评论

        本文标题:synchronized的对象锁和类锁的区别

        本文链接:https://www.haomeiwen.com/subject/fypvwktx.html