线程安全的前提:
1.保证原子性
2.保证可见性
3.保证顺序性
一**.volatile关键字的作用**:用来修饰变量,可以保证可见性和顺序性
二.volatile如何保证内存可见性
1.每次读取前必须先从主内存刷新最新的值
2.每次写入前必须立即同步回主内存中
也就是说,在多线程中,用volatile修饰的变量,每个线程随时看到的都是它的最新值,对某个线程来说其他线程对这个变量的修改都是可见的。
三.volatile如何防止指令重排序
这涉及到内存屏障的问题。
内存屏障的作用:
Java中主要有四种内存屏障
1.LoadLoad:保证屏障前面的读先于屏障后面的写
2.StoreStore:保证屏障前面的写操作先于屏障后的写操作
3.LoadStore:保证屏障前面的读操作先于屏障后面的读操作
4.StoreLoad:保证屏障前面的存储操作先于屏障后面的读操作
四.volatile与synchronized的区别
1.synchronized可以锁定当前变量,方法,和一段代码,而volatile只能用来修饰变量
2.synchronized可以同时保证原子性,可见性,顺序性,而volatile并不具备保证原子性的功能。
3.synchronized锁定的变量可以被编译器优化,而volatile修饰的变量不会被优化
4.volatile不会造成线程的堵塞,而synchronized可能会导致线程堵塞
总结:volatile和synchronized都是保证线程安全的手段,但是volatile并不是线程安全的,它只能保证可见性和顺序性,所以必须要和synchronized配合使用才能保证线程安全,volatile会阻止编译器对代码的优化,因此会降低程序的执行的效率,除非有必要,否则能不使用volatile就尽量不要使用。