4.4可见性

导致共享变量在线程中不可见的原因

  • 线程交叉执行

  • 重排序结合线程交叉执行

  • 共享变量更新后的值没有在工作内存和主内存间及时更新

保证可见性可通过

  • synchronized

  • volatile

Synchronized是如何保证可见性的?

JMM规定,使用synchronized

线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从共享内存中重新读取最新的值

线程解锁前,必须把共享变量的最新值刷新到主内存

注意:加锁和解锁是同一把锁

volatile是如何保证可见性的

通过加入内存屏障禁止重排序优化来实现

对volatile变量写操作时,会在写操作后加入一条store屏障指类,将本地内存中的共享变量值刷新到主内存中

对volatile变量读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量

volatile读写屏障如下:

volatile写

StoreStore屏障:禁止上面的普通写和下面的volatile写重排序

StoreLoad屏障:防止volatile写与下面可能有的volatile读/写重排序

volatile读

LoadLoad屏障:禁止下面所有的普通读操作和上面的volatile读写重排序

LoadStore屏障:禁止下面所有的写操作和上面的volatile读重排序

volatile能保证线程安全么?

volatile只能保证可见性(共享变量是主内存中的最新值),但不能保证原子性,故不能保证线程安全。

可用如下代码实验:

volatile的使用场景

  • 作为状态标记量

使用volatile标记变量isInited,即标记上下文是否初始化完成。

线程1负责初始化上下文,初始化成功设置isInited=true。

线程2根据isInited的值决定睡眠还是向下执行代码。

Last updated

Was this helpful?