讲volatile不能保证原子性时会举这么个例子
”
假如某个时刻变量inc的值为10,
线程1对变量进行自增操作,线程1先读取了变量inc的原始值,然后线程1被阻塞了;
然后线程2对变量进行自增操作,线程2也去读取变量inc的原始值,由于线程1只是对变量inc进行读取操作,而没有对变量进行修改操作,所以不会导致线程2的工作内存中缓存变量inc的缓存行无效,所以线程2会直接去主存读取inc的值,发现inc的值时10,然后进行加1操作,并把11写入工作内存,最后写入主存。
然后线程1接着进行加1操作,由于已经读取了inc的值,注意此时在线程1的工作内存中inc的值仍然为10,所以线程1对inc进行加1操作后inc的值为11,然后将11写入工作内存,最后写入主存。
那么两个线程分别进行了一次自增操作后,inc只增加了1。
”
我的疑问在于:
线程2对变量+1写入主存后,线程1的inc缓存不是会变成无效么,这个时候线程1难道不会重新从主内存读取inc的值?
前程1每次,取valitate修饰的变量都会到主存中去取值。此时线程2执行inc++时,分为几个步骤。从主存中获取值,然后+1,再将结果写回主存。如果在线程2从
主存中,获取值后。下一步CPU使用权到了线程1手上,线程1从主存取值,取到的值还是10。此时,由于取到了值,当线程2将值修改为11时。线程1将不会去
主存中,去取值。
valitate只能保证线程每次取变量,都会从主存中获取。不能保证每次获取的值,是最新修改的值。
根据volatile关键字的内存语义,volatile变量具有如下的特性:
1、可见性。对一个volatile变量的读,总是能看到任意线程对这个volatile变量的最后写入值;
2、原子性。对任意单个volatile变量的读/写具有原子性,但是对于volatile++这样的复合操作不具有原子性。
读和写是原子操作;而++操作是复合操作,它是由如下三个操作组成的:
1、原子读(类似于同步),读取到的是最新的值,但是只会去读一次;
2、非原子+操作,线程的本地内存操作,和主存没关系;
3、原子写(类似于同步),只能同时有一个线程往主存写数据;
多个线程同时做++操作的时候,简单的使用volatile是不能保证正确性的。
volatile修饰的变量每次进行操作都会从主内存中拉取一次数据,所以在线程2自增后,线程1在进行自增时(虽然之前已经获取值了,但对其进行自增操作
时依旧在去主内存拉取数据),这样就保证了内存的可见性
volatile只能保持变量的可见性,也就是保证线程读取的值是最新值。至于题主的例子涉及到原子性方面了有点问错方向的样子。