https://www.cnblogs.com/flashsun/p/7270139.html
题描述
有一个类A,提供了三个方法。分别是静态同步方法,非静态同步方法,含有静态代码块的方法
class A{ public static synchronized void print1(){ print(); } public synchronized void print2(){ print(); } public void print3(){ synchronized (new Object()){ print(); } } private static void print(){ while(true){ String threadName = Thread.currentThread().getName(); System.out.println(threadName); } } }
四种情况的输出结果
class Test { // 1.两个线程,同一个类,调用静态同步方法print1 @Test public void test1() { Thread thread1 = new Thread(() -> A.print1()); Thread thread2 = new Thread(() -> A.print1()); thread1.start(); thread2.start(); } // 2.两个线程,同一个对象,调用非静态同步方法print2 @Test public void test2() { A a = new A(); Thread thread1 = new Thread(() -> a.print2()); Thread thread2 = new Thread(() -> a.print2()); thread1.start(); thread2.start(); } // 3.两个线程,不同对象,调用非静态同步方法print2 @Test public void test3() { Thread thread1 = new Thread(() -> new A().print2()); Thread thread2 = new Thread(() -> new A().print2()); thread1.start(); thread2.start(); } // 4.两个线程,同一个对象,调用普通非静态方法(带有同步代码块)print3 @Test public void test4() { A a = new A(); Thread thread1 = new Thread(() -> a.print3()); Thread thread2 = new Thread(() -> a.print3()); thread1.start(); thread2.start(); } }
问题答案
先直接报上答案:
- 一直输出“Thread-1”
- 一直输出“Thread-1”
- 交替输出“Thread-1”和“Thread-2”
- 交替输出“Thread-1”和“Thread-2”
问题本质分析
不废话,直接点出,这四个问题只要明白两件事即可:
- 一个线程是否能执行被同步了的方法,主要看是否能拿到锁对象
- 静态方法的同步锁是类对象本身,非静态方法的同步锁是实例对象本身,同步代码块的同步锁是括号中传入的对象
所以
- 如果两个线程执行方法用到了同一个锁对象,则一个线程执行时,另一个线程必须等待其释放锁才能拿到锁,所以此时两个线程会互斥
所以
- 1中两个线程执行方法的锁对象都是类对象A,所以线程之间互斥
- 2中两个线程执行方法的锁对象都是实例对象a,所以线程之间互斥
- 3中两个线程执行方法的锁对象分别是new出来的两个实例对象a,所以线程互不影响
- 4中两个线程执行方法的锁对象分别是new出来的两个实例对象object,所以线程互不影响