查看完整视频
小黑屋思过中,禁止观看!
评论并刷新后可见

您需要在视频最下面评论并刷新后,方可查看完整视频

积分观看

您支付积分,方可查看完整视频

{{user.role.value}}
付费视频

您支付费用,方可查看完整视频

¥{{user.role.value}}
课程视频

开通VIP,畅学所有专题课程视频

会员专享

视频选集

Synchronized的底层实现原理,源码深度剖析!

  • 课程笔记
  • 交流讨论

在Java中,我们经常使用synchronized关键字来解决多线程的同步安全问题。更重要的是在Java面试中,synchronized属于必考点,需要掌握的知识点非常多。

为了助大家掌握好synchronized,本节课我重点会讲解以下6点:

1.Synchronized

2.Synchronized方法锁、对象锁、类锁

3.Synchronized的源码实现

4.Synchronized的实现原理

5.Monitor对象详解

6.Synchronized的锁存储位置

Synchronized

Synchronized翻译为中文的意思是同步,也称之为”同步锁“,Synchronized关键字是java并发编程中必不可少的工具,它一次只允许一个线程进入特定代码段,从而避免多线程同时修改同一数据。

Synchronized的作用

在并发编程中存在线程安全问题,主要原因有:
1.存在共享数据
2.多线程共同操作共享数据

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。

Synchronized的三种使用方式

Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:

1.普通同步方法(实例方法):锁是当前实例对象 ,进入同步代码前要获得当前实例的锁。

/**
* 用在普通方法
*/
private synchronized void synchronizedMethod() {
System.out.println("--synchronizedMethod start--");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--synchronizedMethod end--");
}

2.静态同步方法:锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁。

/**
* 用在静态方法
*/
private synchronized static void synchronizedStaticMethod() {
System.out.println("synchronizedStaticMethod start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedStaticMethod end");
}

3.同步方法块:锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

/**
* 用在类
*/
private void synchronizedClass() {
synchronized (SynchronizedTest.class) {
System.out.println("synchronizedClass start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedClass end");
}
}

Synchronized的源码实现

package com.mikechen.concurrent.lock;

public class SynchronizedAnalysis {

public synchronized void test1(){

System.out.println("welcome to mikechen");
}

public void test2(){
synchronized (this){
System.out.println("welcome to mikechen");
}
}

}

反编译后
Synchronized的底层实现原理,源码深度剖析!-mikechen的互联网架构师之路

1、同步方法

使用ACC_SYNCHRONIZED标记符隐式的实现

2.同步代码块

monitorenter(获取锁)、monitorexit(释放锁)
两者虽然实现细节不同,但本质上都是对一个对象的监视器(monitor)的获取

Synchronized的实现原理

隐藏内容,您需要满足以下条件方可查看
End

这节课就先讲到这里,后面一节课我会重点去讲解Synchronized的锁的详细升级过程(这也是大厂经常面试的考点)。

5 条回复 A文章作者 M管理员
  1. 李鸿翼

    synchronized是同步锁,有三种使用方法,包括普通方法、静态方法、以及代码块锁对象。
    普通方法锁当前对象,静态方法锁当前类对象,代码块锁指定的对象。
    锁方法底层实现是用了一个acc同步标志位来标志该方法是否加锁,代码块锁是在代码块前面和后面加了moniterenter,moniterexit指令。
    虽然这两种方法实现有差异,但本质都是去获取一个moniter对象,获取到锁后,moniter对象的计数器加1,释放后,减一,如果变为0,代表锁已经完全释放,支持锁重入。

    每个对象包括对象头、实例数据、对齐填充。其中对象头里的标记字段包含了锁的相关信息

    • mikechen

      核心点都谈到了,synchronized的底层实现还有一个非常关键的点就是:锁的升级与优化,这个也是经常考察的点,刚好今天我讲到了这点,回头再把这个点补下就更好了 ✗咧嘴笑✗

  2. 路正银

    synchronized是java的关键字,当它用来修饰一个方法或者代码块的时候,能够保证在同一时刻只有一个线程执行该段代码。JDK1.5之后引入了自旋锁、锁粗化、轻量级锁、偏向锁来优化关键字的性能。
    synchronized的底层实现是通过一个monitor的对象来完成,具体的指令有monitorenter和monitorexit。

    • mikechen

      synchronized的锁优化特别重要的,严格来讲顺序是:无锁->偏向锁->轻量级锁->重量级锁,从轻量级锁到重量级锁会涉及到你上面提到的两个核心点:自旋锁与自适应自旋锁,刚好今天我讲了锁的升级,作业也提到了这点,回头可以作业输出后,你会有新的收获,路正银加油 ✗拳头✗

  3. JansenZhang

    synchronized是java提供的一个同步锁的关键字,java使用这个关键字来实现对代码块的加锁操作,从而保证在多线程的情况下只有一个线程能访问到被synchronized包住的代码块。
    synchronized根据使用位置的不同分为普通方法锁,静态方法锁和代码块锁,锁的对象分别是当前实例对象,当前类对象和自定义对象。
    虽然synchronized使用位置不同,但是底层的实现都是通过获取对象的监视器monitor来实现,在被synchronized标记的代码前后,会插入monitorenter和monitorexit指令。monitorenter会让当前线程获取用户对象的锁,如果获取成功,monitor的计数器就+1,这样别的线程就无法再获取到锁,当前线程执行sychronized的代码块,执行完成代码后会执行monitorexit,将monitor的计数器-1,当monitor的计数器=0的时候就代表解锁成功,允许别的线程获取锁。