个人学习笔记

参考作者

在多线程中经常会用到 synchronizedvolatile 这两个关键字;

# synchronized

修饰方法或者代码块:在任意时刻只能有一个线程执行;可以把任何一个非 NULL 对象当做锁。

使用:

  • 修饰实例方法:给当前对象实例加锁,进入同步代码之前需要获得当前对象实例的锁。锁住的是对象的实例 (this)。
  • 修饰静态方法:给当前类加锁,进入同步代码之前需要获得当前类的锁。锁住的是 Class 实例,又因为 Class 的相关数据存储在永久带 metaspace, 永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁住调用该方法的全部线程。
  • 修饰代码块:指定加锁对象,给指定对象加锁(锁住的是所有以该对象为锁的代码块),进入同步代码块之前需要获得指定对象的锁。

# volatile

关键字 volatile 解决的是变量多个线程之间的可见性,该关键字修饰的变量会直接在主内存中进行读写操作,保证了变量的可见性。

volatile 是比 synchronized 更轻量级的同步锁,它在多线程开发中保证共享变量的 “可见性”。其执行成本更低,因为它不会引起线程上下文切换和调度,(效率高)。在访问 volatile 变量时不会执行加锁操作

注意:volatile 变量不会被缓存在寄存器或者其他处理器不可见的地方,因此在读取 volatile 类型的变量时总会返回最新写入的值。(变量可见性其一是保证该变量对所有线程可见,这里的可见指的是当一个线程修改了变量的值,那么新的值对于其他线程是立即获取的。)

保证两个条件保证并发环境的线程安全:

  • 对变量的写操作不依赖于当前值(eg: i++), 或者说是单纯的变量赋值(boolean flag = true)。
  • 该变量不包含在其他变量的不变式中(不同的 volatile 变量之间不能相互依赖),只有在状态真正独立于程序内其他内容时才能使用 volatile。

Volatile 防止指令重排,在 DCL 中,防止高并发情况下,指令重排造成的线程安全问题。

# JAVA 中线程锁机制是怎样的?

1.java 的锁就是在对象的 Markword 中记录一个锁状态

无锁、偏向锁、轻量级锁、重量级锁对应不同的锁的状态。

JAVA 的锁机制就是根据资源竞争的激烈程度不断进行锁升级的过程。

# 检测

  1. 关键字 synchronized 解决的是什么问题? 10

    解决的是多个线程之间访问资源的同步性。

    8.4

  2. 关键字 volatile 有哪两个作用?10

    关键字 volatile 的作用是保证变量的可见性,以及防止指令进行重排序优化。

    8.4

更新于

请我喝[茶]~( ̄▽ ̄)~*

Jean 微信支付

微信支付

Jean 支付宝

支付宝

Jean 贝宝

贝宝