内存模型和线程
由于处理器的速度与存储和通讯子系统之间的速度相差太大,所以出现了并发和缓存等技术,来减弱这种差距。
本节简要介绍Java内存模型,volatile变量。
Java内存模型
每个线程都会保持一个工作内存,线程对于变量的操作,都在工作内存中进行,操作完成之后,再刷新至主内存。其模型如下:
内存操作:
- lock(锁定)
- unlock(解锁)
- read(读取)
- load(载入)
- use(使用)
- assign(赋值)
- store(存储)
- write(写入)
volatile变量
两种特性:
可见性,变量对所有线程可见;即任一线程对于变量的修改,其他线程可以观测的到。
禁止指令重排序优化。请看代码:
Configuration config ;
volatile boolean isInitialed = false;
//以下代码在线程A中执行
config = new Congiguration();
isInitialed = true;
//以下代码在线程B中执行
if(!isInitialed){
sleep();
}
doSthWithConfig();
如果不添加volatile修饰符,那么有可能执行指令重排序优化,“isInitialed = true”可能在”config = new Configuration()“之前执行,当切换到线程B时,就会执行”doSthWithConfig()”,程序出错。
Java并发特征
- 原子性
- 可见性
- 并发性
先行发生原则
Java并发代码的一些默认的发生顺序,满足先行发生原则,即不作任何约束它也会满足的顺序:
- 程序次序规则:同一线程内,书写顺序即执行顺序。(疑惑:单线程也会发生指令重排序,这条规则是否只是概念性的?)
- 管程锁定规则
- volatile变量规则
- 线程启动规则
- 线程中断规则
- 线程终止规则
- 对象终结规则
- 传递性
线程安全
- 不可变:如final,String类对象
- 绝对线程安全:大多数都不是绝对线程安全
- 相对线程安全:通常意义上的线程安全
- 线程兼容:本身不是线程安全,通过其他手段保证
- 线程对立:不能并发的代码
结束语
由于本人知识水平有限,这本《深入理解Java虚拟机》读了好几遍才敢写这一系列博客,但还是难免有错误,希望大家批评指正。这本书还有许多值得学习的地方,强烈推荐,看多少遍都不为过谢谢大家。