volatile和内存模型(多线程)
1.java内存模型
概述:jvm规范中定义的一种模型,描述java程序中各种变量(线程共享变量)的访问规则,已经在jvm中将变量存储到内存和从内存中读取变量的细节
- 所以的共享变量都存储在主内存。这里说的变量指实例变量和类变量,不包括局部变量,因为局部变量是线程私有的。
- 每个线程存在自己的工作内存,线程工作内存中保存了被线程使用变量的工作副本
- 线程对变量的所以操作(读写)都必须在工作内存中完成,不能直接读取主内存中的变量
- 不同线程之间不能直接访问对方工作内存中的变量,线程之间值得传递,需要通过主内存中转完成
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V0jYT699-1583466302913)(D:\学习文件\博课\java\img\java内存模型.png)]
- 线程中的副本内存的共享变量,当对副本中的共享变量副本进行操作时,会同步到主内存中,线程再从主内存中读取。
2.多线程下变量的不可见性
在线程运行时,多个线程修改共享的成员变量,会出现一个线程修改了共享变量,另一个线程不能立即看到修改后的最新值(就是共享内存值改变了,另一个线程工作内存中的共享变量副本值没有更新导致的)
解决方案:
一加锁:
加锁后的工作流程:
①线程获取锁 ②清空工作内存 ③从主内存拷贝共享变量最新值到工作内存 ④执行线程代码
⑤若有修改内容同步到主内存 ⑥释放锁
二volatile
3.volatile
volatile关键字
功能:
被它修饰时,它会保证修改的值立即被更新到主内存,当有线程读取时,它会立即去内存中读取最新值
特性:
1.实现了多线程中变量的可变性
(线程的工作空间就是本地内存)
原理:当写时,被volatile修饰的变量,jvm会把对应本地内存中的共享变量值刷新到主内存中。
读时,jvm会把线程对应本地内存中valatile修饰的变量置为无效,线程再从主内存读取共享变量并更新到本地内存中。
2.volatile不保证原则性,所以不能代替锁机制
原则性值在一次或多次操作中,要么所有操作都执行且不会受到任何因素干扰而中断,要么都不执行。
3.禁止指令从排序
重排序指为了提高性能,编译器常常会对既定的代码执行顺序进行指令重排序
应用场景:
-
状态标识
-
原子性的赋值操作
-
开销低的读写锁策略
当读远远大于写,结合使用内部锁和volatile修饰变量来减少同步的开锁
利用volatile保证读取的可见性,synchronized保证复合操作的原子性
合使用内部锁和volatile修饰变量来减少同步的开锁
利用volatile保证读取的可见性,synchronized保证复合操作的原子性