文章目录
1. 线程安全问题
1.1 线程安全概念
在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。也就是多个线程访问同一个对象时,如果不用其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
1.2 线程不安全因素
- 抢占式执行
- 多个线程同时修改了同一个变量
- 非原子性操作
- 内存可见性问题
- 指令重排序问题
使用锁是 Java 中解决线程安全问题中最重要的手段。
2. volatile 关键字
2.1 volatile 的作用
volatile 可以解决内存可见性和指令重排序的问题。
- volatile 保证变量对所有线程的可见性:代码在写入 volatile 修饰的变量时,改变线程工作内存中 volatile 变量的值,修改后的值会立即从工作内存刷新到主内存中,新值对所有线程会立即更新。代码在读取 volatile 修饰的变量时,先从主内存中读取 volatile 变量的最新值到线程的工作内存中,再从工作内存中读取 volatile 变量的副本值。所以说多线程环境下 volatile修饰的变量值一定是最新的。
- jdk1.5以后 volatile 完全避免了指令重排优化,实现了有序性。
2.2 volatile 的使用
2.2.1 保证内存可见性
不可见性问题主要指一个线程修改了共享变量值,而另一个线程却看不到。volatile 关键字可以保证内存可见性。
public class VolatileTest {
int a = 1;
int b = 2;
public void change(){
a = 3;
b = a;
}
public void print(){
System.out.println("b&