Android开发Android技术知识Android开发经验谈

类锁、对象锁使用实战

2021-06-07  本文已影响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.类锁对该类的所有对象都能起作用,而对象锁对该类不同对象不起作用。

上一篇 下一篇

猜你喜欢

热点阅读