java关键字transient,volatile

被transient关键字修饰的变量不会被序列化

被volatile关键字修饰的变量,每次被线程访问时,都会强制从共享内存中重读改变量的值,但是不具备原子性

被volatile关键字修饰的变量的,具有以下两点特性:

  1. 保证了不同线程对该变量操作的内存可见性,不保证原子性。
  2. 禁止指令重排序

在java的内存模型中,JMM规定对于多个线程共享变量都存在主存中的,每个线程包含自己的工作内存,工作内存保存了主内存共享的变量,
其中一个线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步会主内存中。在其他线程未将共享变量同步
会自己的工作内存之前,共享变量的改变对其不可见的。也就是说其他线程的工作内存中的变量已经过时了。

volatile是通过内存屏障和禁止指令重排序来保证内存可见性的,一个线程对volatile变量的修改,能即刻被其他线程所见,
但是不保证原子性。

使用volatile提供理想的线程安全,需要满足以下两个条件:

  1. 对变量的写操作不依赖于当前值
  2. 该变量没有包含在具有其他变量的不变式中

volatile变量不能用来做线程安全的计数器

volatile的适用场景

1. 状态标志

注意:这种状态标记通常只有一种状态转换如果需要状态的来回转换,可以使用原子变量。

2. 一次性安全发布

3. 独立观察

定期“发布”观察结果供程序内部使用

4. “volatile bean”模式

5. 开销较低“读-写锁”策略


  • 状态位
  • 一个线程写,多个线程读的场景