volidate与可见性

volidate是java中用来保证并发访问同一状态的可见性的一种工具。可见性是指一个线程对内存中某一地址的值修改一定能对其余访问该地址的线程生效。听起来是个理所固然的事,但这简单的事背后却有一套复杂的机制来保证。其复杂机制产生的缘由是在cpu和内存间加入缓存所致使的,缓存协调了CPU和内存间效率不一致的问题,但引入了内存不可见的问题。cpu访问内存时,一次性将内存中的一页读到缓存中,再从缓存中读取指定地址的值用于操做,若是当某一个cpu修改了某地址的状态的同时又有另外一个cpu同时也对该地址进行读或者写,可想而知在两个缓存中同一地址的值极可能是不一样的,那么哪一个缓存中的值应该被写回内存中呢?凡事讲个先来后到,因此cpu先写回的缓存应该写回内存,而另外一个缓存的值将变为无效。这种机制经过mesi协议来保证,mesi表明了缓存的四种状态,每一个缓存监听其余缓存的状态变化,据此改变自身的状态。E表明该地址被cpu独占,没有其余cpu的缓存有该地址;而当另外一个cpu也要访问该地址时,以前的cpu该地址缓存状态变为s,同时新来的cpu的该缓存地址状态也是s,因此s表示该地址共享;若是两个cpu中的一个对该地址进行写操做,那么这一个cpu的该地址状态就变为m,而另外一个cpu的缓存中该地址将变为i,因此m就表明修改,i表明无效。被修改的地址的值应该被写回内存中,但这个效率和cpu的运行效率相比很是慢,若是cpu等待地址对应的值写回内存,什么事都不干就太浪费了,因此就先不写回内存。但修改的值确定必定必须写回内存,那么就引入了storeBuffers和无效队列这两个组件。cpu对地址的值写再也不直接写入缓存而是storebuffers中,cpu可当即往下执行。storebuffers在某一时刻向无效队列写入消息,当即得到响应,而无效队列按队列顺序设置缓存中的地址状态为无效。那么问题就来了,由于改变的状态没有同步更新,其余cpu可能在别的cpu改写地址的值时去读取地址的值,这就产生了状态不一致的问题。硬件上没法肯定哪一个操做应该优先,因此提供memorry barrier给软件来控制操做的前后。java中volidate就是用来表示memorry barrier,当对volidate修饰的变量赋值时那么编译器会添加一个write memorry barrier,其做用是将缓存中的状态写回内存;当对volidate修饰的变量赋值时那么编译器会添加一个read memory barrier,其做用是强制读内存中状态java

相关文章
相关标签/搜索