1.一旦共享变量被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的;
2)禁止进行指令重排序。
2.所谓volatile的措施,就是
1)每次从内存中取值,不从缓存中拿值。这就保证了用volatile修饰的共享变量,每次的更新对其他线程立即。既然保证了其他线程的立即可见,也就无法保证原子性。
2)由于有些时候对volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。
/**
* 功能:发起50个线程,每个线程对race变量进行10000次自增操作,如果代码能够正确并发,则最终race的结果应为500000,但是实际的运行结果却小于20000.
* @author NST_Xx
*
*/
public class VolatileTest {
public static volatile int race = 0;
public static void increase(){
race++;
}
private static final int THREADS_COUNT = 50;
public static void main(String[] args) {
Thread[] threads = new Thread[THREADS_COUNT];
for(int i=0;i<THREADS_COUNT;i++){
threads[i] =new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0;i<10000;i++){
increase();
}
}});
threads[i].start();
}
while(Thread.activeCount()>1)
Thread.yield();
System.out.println(race);
}
}
运行结果
460311<500000,这是由于race++操作不是原子操作,导致一些线程对race变量的修改丢失。
注:参考牛客网讨论