Skip to content

Latest commit

 

History

History
34 lines (18 loc) · 1.91 KB

03第三章:对象的共享.md

File metadata and controls

34 lines (18 loc) · 1.91 KB

3.1.2 非原子的 64 位操作

Java 内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非 volatile 类型的 longdouble 变量,JVM 允许将 64 位的读操作或写操作分解为两个 32 位的操作。

当读取一个非 volatile 类型的 long 变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高 32 位和另一个值的低 32 位。

3.1.4 volatile 变量

当把变量声明为 volatile 类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。

volatile 变量不会被缓存在寄存器或者对其他处理器不可见的地方,因为在读取 volatile 类型的变量时总会返回最新写入的值。

volatile 变量通常用做某个操作完成、发生中断或者状态的标志。

volatile 变量确保可见性,不确保原子性。

当且仅当满足以下所有条件时,才应该使用 volatile 变量:

  • 对变量的写入操作不依赖变量的当前值
  • 该变量不会与其他状态变量一起纳入不变性条件中
  • 在访问变量时不需要加锁

3.3.3 ThreadLocal 类

ThreadLocal 提供了 getset 等访问接口和方法,这方法为每个使用该变量的线程都存有一份独立的副本,因此 get 总是返回由当前执行线程在调用 set 时设置的最新值。

ThreadLocal 对象通常用于防止对可变的单实例变量或全局变量进行共享。

3.4.1 final 域

final 类型的域是不能修改的,但是如果 final 域所引用的对象是可变的,那么这些被引用的对象是可以修改的。

在 Java 内存模型中,final 域能确保初始化过程的安全性,从而可以不受限制的访问不可变对象,并在共享这些对象时无须同步。