一.内存模型的相关概念
- 不同的平台,内存模型是不一样的,但是jVM的内存模型规范是统一的
- 线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型多线程下要解决2个主要问题:可见性和有序性。
- 我们都知道计算机有高数缓存的存在,处理器并不是每次处理数据都是取内存。JVM定义了自己的内存模型,屏蔽了底层累成管理的细节。
它的内存模型工作原理如下图
线程执行的时候,首先从主内存读取值,再load到工作累成中的副本中然后传给处理器执行,执行完毕给副本赋值,随后工作累成再把值传给主内存,值才跟新。
二 并发编程中的三个概念
- 原子性 :只有简单的读取,赋值才是原子性
- 可见性:多个线程访问一个变量时,一个线程修改了这个变量,其他线程可以立即看到修改的值改变
- 有序性:在java内存模型中,允许编译器和处理器对指令进行重排序,但是排序过程不会音响到单线程的执行,却会影响到多线程并发执行的正确
三 volatile关键字
java语言提供了一种稍弱的同步机制,即volatile变量,用来却保将变量的跟新操作通知到其他线程。当把变量声明为volatile类型后,编译器于运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他累成操作一起重排序。volatile变量不会被缓存在放在对其他的处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入值。
一旦一个共享变量(类的成员变量,类的静态成员变量)被volatile修饰之后,那么就具备了两层语言:
- 1.保存多线程下的可见性
- 2.禁止进行指令重排序(即保证有序性)。
如下图是使用volatile的前后
四 volatile的原理和实现机制
- 它确保指令重排序时不会把其后面的指令排到累成屏障之前的位置,也不会把前面的指令排到内存屏障后面。
- 它会强制将对皇城的修改操作立即写入主存
- 如果是写操作,他会导致其他的cpu中队友的缓存执行无效
- 它的使用前提是对变量的写操作不依赖当前的值
- 该变量没有包含在具有其他变量的不变式总,简单的说就是保证该操作是原子性操作
五 volatile的使用场景
1 volatile bean模式
2 开销较低的读写-写锁
六 syschronized和volatile的异同如下图