类锁、对象锁使用实战

作者: 奔跑吧李博 | 来源:发表于2021-06-07 09:43 被阅读0次

前提,synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。

对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。

在LockTask类中定义三个方法,task1方法和task2方法为类锁,task3方法为对象锁。

class LockTask {

    public synchronized static void task1() {
        System.out.println(Thread.currentThread().getName() + "start");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }

    public synchronized static void task2() {
        System.out.println(Thread.currentThread().getName() + "start");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }

    public synchronized void task3() {
        System.out.println(Thread.currentThread().getName() + "start");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }

}

创建三个线程类,分别执行task1,task2,task3:

    static class Thread1 extends Thread {
        LockTask lockTask;

        public Thread1(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task1();
        }
    }

    static class Thread2 extends Thread {
        LockTask lockTask;

        public Thread2(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task2();
        }
    }

    static class Thread3 extends Thread {
        LockTask lockTask;

        public Thread3(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task3();
        }
    }

创建三个线程,执行同一个lockTask对象的三个方法:

    public static void main(String[] args) {
        LockTask lockTask = new LockTask();
        Thread1 thread1 = new Thread1(lockTask);
        Thread2 thread2 = new Thread2(lockTask);
        Thread3 thread3 = new Thread3(lockTask);

        thread1.setName("thread1");
        thread2.setName("thread2");
        thread3.setName("thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }

执行顺序为:


因为task1和task2方法都是类锁,所以多线程执行方法执行同一个类锁,所以task1和task2方法是同步执行的,task3与task1、task2是异步执行的。

修改示例改为使用对象锁:
class LockTaskTest2 {

    static class Thread1 extends Thread {
        LockTask lockTask;

        public Thread1(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task3();
        }
    }

    static class Thread2 extends Thread {
        LockTask lockTask;

        public Thread2(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task3();
        }
    }

    public static void main(String[] args) {
        LockTask lockTask = new LockTask();
        LockTask lockTask2 = new LockTask();
        Thread1 thread1 = new Thread1(lockTask);
        Thread2 thread2 = new Thread2(lockTask2);

        thread1.setName("thread1");
        thread2.setName("thread2");
        thread1.start();
        thread2.start();
    }
}

执行结果:


两个线程执行task3方法,为对象锁方法,只会锁住同一对象,lockTask与lockTask2为不同对象,所以会异步执行。

修改示例改为多线程使用类锁,只将执行task3方法改为task1方法:
class LockTaskTest2 {

    static class Thread1 extends Thread {
        LockTask lockTask;

        public Thread1(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task1();
        }
    }

    static class Thread2 extends Thread {
        LockTask lockTask;

        public Thread2(LockTask lockTask) {
            this.lockTask = lockTask;
        }

        @Override
        public void run() {
            lockTask.task1();
        }
    }

    public static void main(String[] args) {
        LockTask lockTask = new LockTask();
        LockTask lockTask2 = new LockTask();
        Thread1 thread1 = new Thread1(lockTask);
        Thread2 thread2 = new Thread2(lockTask2);

        thread1.setName("thread1");
        thread2.setName("thread2");
        thread1.start();
        thread2.start();
    }
}

执行结果:


两个线程执行task1方法,为类锁方法,lockTask与lockTask2虽然为不同对象,但是类锁对该类所有对象都起加锁作用,thread1拿到LockTask类锁,执行完task1方法,thread2才能拿到类锁执行task1方法,所以会同步执行。

总结:

1.如果多线程同时访问同一类的类锁以及对象锁,这两个方法执行是异步的,原因:类锁和对象锁是2中不同的锁,可以各自持有锁。

2.类锁对该类的所有对象都能起作用,而对象锁对该类不同对象不起作用。

相关文章

  • 类锁、对象锁使用实战

    前提,synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronize...

  • synchronized与volatile原理

    synchronized使用 修饰实例方法:锁对象是当前实例对象 修饰静态方法:锁对象是当前类的Class对象 修...

  • 让你不再害怕JAVA的锁(一)

    java中的同步锁包括对象锁和类锁。 对象锁: 针对的是具体的对象实例;类锁:针对的是整个class类 现在先让我...

  • MySQL的锁怎么解?

    大家都知道java里面的synchronized,对象锁。(这里不扯什么类锁,对象锁,类锁其实就是Class对象的...

  • java类锁和对象锁

    java对象锁有两种:对象锁、类锁。 对象锁:在非静态方法上加锁。声明了一个对象锁。类锁:在静态方法上加锁,声明了...

  • synchronized

    类锁和对象锁

  • Synchronized的使用

    锁的类型 类锁:只有synchronized修饰静态方法或者修饰一个类的class对象时,才是类锁。 对象锁:除了...

  • synchronized 修饰静态方法、普通方法与代码块的区别

    概念: 类锁:所有对象共用一个锁 对象锁:一个对象一把锁,多个对象多把锁。 一、synchronized修饰普通方...

  • synchronized :同步锁

    synchronized 同步锁分为对象锁、类锁、静态方法锁、非静态方法锁等。其中对象锁和非静态方法锁的作用域是对...

  • 线程、多线程和线程池 二

    1.对象锁和类锁是否会互相影响? · 对象锁:Java的所有对象都含有1个互斥锁,这个锁由JVM自动...

网友评论

    本文标题:类锁、对象锁使用实战

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