查看完整视频
评论可见

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

积分观看

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

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

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

¥{{user.role.value}}
专属视频

只允许以下等级用户查看该视频

升级
会员专享

Synchronized的底层实现原理

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

接下来,我会用3节课来重点解决synchronized,让你彻底理解synchronized的使用与实现原理。

这节课,我先从synchronized的底层实现原理开讲,重点会谈到以下6点:

  • Synchronized
  • Synchronized方法锁、对象锁、类锁
  • Synchronized的源码实现
  • Synchronized的实现原理
  • Monitor对象详解
  • 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的源码实现

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

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

课后作业

这是一道去阿里的面试题。

1.谈谈你synchronized 关键字的理解?

2.紧接着:再谈谈synchronized的底层实现原理?

请把你的答案写到问答区域,一课一练。(输出是最好的学习:每一次输出都会让你离目标更进一步)

并发锁

史上最强Synchronized锁升级详解

2020-7-7 12:12:57

分布式缓存

Redis分布式存储实现原理精讲,含N多大厂必考点!

2020-11-16 19:24:04

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

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

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

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

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

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

个人中心
今日签到
搜索