聊聊synchronized的锁问题

Posted 闪客sun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊synchronized的锁问题相关的知识,希望对你有一定的参考价值。

本文不会特别深入细致地讨论synchronized,只是做一个通俗易懂的说明,以及看清一类问题的本质,希望能给大家一点启发。

 

问题描述

有一个类A,提供了三个方法。分别是静态同步方法,非静态同步方法,含有静态代码块的方法

 1 class A{
 2     public static synchronized void print1(){
 3         print();
 4     }
 5     public synchronized void print2(){
 6         print();
 7     }
 8     public void print3(){
 9         synchronized (new Object()){
10             print();
11         }
12     }
13     private static void print(){
14         while(true){
15             String threadName = Thread.currentThread().getName();
16             System.out.println(threadName);
17         }
18     }
19 }

 

请回答一下四种情况的输出结果

 1 class Test {
 2     // 1.两个线程,同一个类,调用静态同步方法print1
 3     @Test
 4     public void test1() {
 5         Thread thread1 = new Thread(() -> A.print1());
 6         Thread thread2 = new Thread(() -> A.print1());
 7         thread1.start();
 8         thread2.start();
 9     }
10     // 2.两个线程,同一个对象,调用非静态同步方法print2
11     @Test
12     public void test2() {
13         A a = new A();
14         Thread thread1 = new Thread(() -> a.print2());
15         Thread thread2 = new Thread(() -> a.print2());
16         thread1.start();
17         thread2.start();
18     }
19     // 3.两个线程,不同对象,调用非静态同步方法print2
20     @Test
21     public void test3() {
22         Thread thread1 = new Thread(() -> new A().print2());
23         Thread thread2 = new Thread(() -> new A().print2());
24         thread1.start();
25         thread2.start();
26     }
27     // 4.两个线程,同一个对象,调用普通非静态方法(带有同步代码块)print3
28     @Test
29     public void test4() {
30         A a = new A();
31         Thread thread1 = new Thread(() -> a.print3());
32         Thread thread2 = new Thread(() -> a.print3());
33         thread1.start();
34         thread2.start();
35     }
36 }

 

 

问题答案

先直接报上答案:

  1. 一直输出“Thread-1”
  2. 一直输出“Thread-1”
  3. 交替输出“Thread-1”和“Thread-2”
  4. 交替输出“Thread-1”和“Thread-2”

 

问题本质分析

不废话,直接点出,这四个问题只要明白两件事即可:

  • 一个线程是否能执行被同步了的方法,主要看是否能拿到锁对象
  • 静态方法的同步锁是类对象本身,非静态方法的同步锁是实例对象本身,同步代码块的同步锁是括号中传入的对象

所以

  • 如果两个线程执行方法用到了同一个锁对象,则一个线程执行时,另一个线程必须等待其释放锁才能拿到锁,所以此时两个线程会互斥

所以

  • 1中两个线程执行方法的锁对象都是类对象A,所以线程之间互斥
  • 2中两个线程执行方法的锁对象都是实例对象a,所以线程之间互斥
  • 3中两个线程执行方法的锁对象分别是new出来的两个实例对象a,所以线程互不影响
  • 4中两个线程执行方法的锁对象分别是new出来的两个实例对象object,所以线程互不影响

Game Over

以上是关于聊聊synchronized的锁问题的主要内容,如果未能解决你的问题,请参考以下文章

大厂JAVA核心技能来聊聊Java的锁使用

大厂JAVA核心技能来聊聊Java的锁使用

Java——聊聊JUC中的锁(synchronized & Lock & ReentrantLock)

Java——聊聊JUC中的锁(synchronized & Lock & ReentrantLock)

Java——聊聊JUC中的锁(synchronized & Lock & ReentrantLock)

Java——聊聊JUC中的锁(synchronized & Lock & ReentrantLock)