Java Momory Model



## JMM(Java Momory Model)模型
	多线程下java代码的执行顺序,共享变量的读法。
	* 编译器优化
	* Processor优化
	* 缓存优化 
	会导致代码执行顺序变化
	
### JMM规范
##### Race condition(竞态条件)
	在多线程下,没有依赖关系代码,在执行共享变量读写操作(至少由一个线程写时),并不能保证以编写顺序执行,这成为发生了竞态条件。
	竞态条件是为了更好的性能
	
##### Synchronization Order (同步动作) -一个线程中代码的执行顺序
	若要保证多线程下,每个线程的执行顺序按照编写顺序执行,那么必须使用Synchronization Actions来保证
	lock,unlock 对性能影响最大,但是最强 Synchronization
		原理:
			反编译代码后,二进制执行时,通过 monitorenter 加锁, 通过 monitorexit 解锁。
			在加锁时候,想系统申请 Monitor 锁,由C++实现。
	volatile 方式读写变量 对性能影响其次 - 保证可见性,防止重排序
		原理:
			写入:	
				↑ LoadStore + StoreStore
				store(操作)
				↑ Store  ↓Load
			读取:
				load(操作)
				LoadLoad + LoadStore
			
			visibility 及时是多次读取同一变量,所得结果不合理
			partial ordering 单个属性注解valatile
				volatile 写要放在最后 volatile 读要放在最后
				
			total ordering 	全部属性注解valatile
		*** CAS(对属性操作的原子性) + volatile = 原子性
			
	VarHandle 方式读写变量,jdk9后推出
	
###### 内存屏障
	共有四种,具体实现与cpu架构相关
	1, LoadLoad 防止B的load重排到A的load之前
		read(A)
		LoadLoad
		read(B)
		
	2,LoadStore 读取写入
	
	3,StoreStore 写入写入
	
	4,*StoreLoad(发生在线程切换时,屏障前的改动都会同步到主存中,屏障后的Load获取主存中最新数据) 写入读取
	
	Acquire=LoadLoad + LoadStore
	Release=StoreStore + LoadStore
	
##### Heappens-Before (在命令之前出现) -线程切换时代码执行顺序和可见性
	若是变量读写时候发生线程切换(例如:线程1写入x,切换到线程2,线程2读取x)在这些边界的处理上如果有action1优先于action2发生,
	那么代码可以按确定的执行顺序执行,称之为Heappens-before order规则
	触发Heappens-Before条件
		1,线程的启动和运行边界
			T1(x = 10) → T1(t2.start())
					  → T2(run())
					  → T2(x == 10)
					  
		2,线程的结束和 join 边界
			T1(x = 10) → T1(terminated)
					  → T2(t1.join)
					  → T2(x == 10)
					  
		3,线程的打断和得知打断边界
			T1(x = 10) → T1(t2.interrupt())
					  → T2(this.isInterrupted())
					  → T2(x == 10)
					  
		4,unlock 与 lock 边界
			T1(x = 10) → T1(unlock(obj))
					  → T2(lock(obj))
					  → T2(x == 10)
					  
		5,volatile write 与 volatile read 边界(写在读的前面才会触发)
			T1( volatile x = 10) → T2( volatile x == 10 )
			
		6,传递性
			T1(x = 10) → T1(unlock(obj))
					  → T2(lock(obj))
					  → T2(x == 10)
					  → T2(terminated)
					  → T3(t2.join())
					  → T3(x == 10)
					  
##### Causality(因果律)
	代码之间存在依赖关系,及时没有加SA(Synchronization Order, Heappens-Before)操作,代码的执行顺序也是可以预见的
	
##### 安全发布
	若要安全构造对象,并将其共享使用,需要使用fianl或者volatile(加在最后一个赋值的变量)修饰其成员变量,避免使用this溢出情况

#### 总结
##### JMM 研究的是
* 多线程下java的执行顺序,实际代码的执行顺序与你编写的代码顺序不同
* 共享变量的读写操作,在竟态条件下,需要考虑共享变量独写的原子性,可见性,有序性


##### 共享变量的问题起因
* 原子性是由于操作系统的分时机制,线程切换导致的
* 有序性和可见性可能来自于编译器优化,处理器优化,缓存优化

##### JMM制定了一些规则,理解这些规则才能写出正确的线程安全的代码
* 竟态条件会导致代码顺序被重排
* 利用synchronized, volatile 一些SA,可以控制线程内代码的执行顺序
* 线程切换时的执行顺序与可见性,遵守HB规则
* HB规则还不足够,需要因果律作为补充
* 可以通过final或者volatile实现对象的安全发布

##### 从底层理解volatile 与 synchronized 
* 内存屏障
* synchronized是如何解决原子性,可见性,有序性问题的,有哪些优化
* volatile 是如何解决可见性,有序性问题的,与cas结合的为例
* VarHandle 是如何解决可见性,有序性问题的
 


	



























































































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值