1.volatile的作用,防止编译器优化。例如一个线程需要操作一个全局变量,为了使得效率更高,它会把这个全局变量首先加载到通用寄存器中,以后再次操作这个全局变量的时候,他将直接从寄存器中取出数据,而不是这个变量的实际地址处得到数据。假如在这期间一个线程或者一个中断打断了程序的执行,并且把这个全局变量的值改了。再回到先前的线程,他将取得一个过期的数据,这显然不是我们想要的。
一般说来,volatile 用在如下的几个地方:
1) 中断服务程序和其他任务共享的变量应该加 volatile。
2) 多任务环境下各任务间共享的变量应该加 volatile,如果使用了同步机制也可以不加。
3) 存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能有不同意义。
2.线程安全,同步机制。防止在多线程或者中断中对共享数据或者资源的同时操作导致数据或资源出现不符合预期的结果。例如一个线程在对全局变量执行a++操作,这条语句转成汇编语句也将是好几条指令,如果在这期间被线程或者中断打断也进行a++操作。这时出现的结果将不是编程者所期待的,这时候可以用原子操作。(这时使用volatile不正确)
3.正确使用同步机制的代码不仅能保证线程安全,而且能防止编译器优化(参考知乎https://zhuanlan.zhihu.com/p/102406978),这时将不用使用volatile。
4.某些时候对于全局变量也可以不用同步机制而只用volatile。例如如果能保证某个线程在操作全局变量的时候,不会被操作该全局变量的中断或者线程打断。或者被打断后,对这个变量的操作将不影响你先前线程的操作。这种情况其实锁机制也能使用。但是我感觉volatile的速度比加锁的方式会更快些。
相关文章
- 12-31golang_并发安全: slice和map并发不安全及解决方法
- 12-31开启新线程QFeature和QFatureWatcher的使用
- 12-31python爬虫之线程池和进程池
- 12-31进程池和线程池、协程、TCP单线程实现并发
- 12-31python2 logging模块在多进程和多线程混用下的一个坑
- 12-31errno多线程安全(转载)
- 12-31iOS之深入探究多线程实现、线程死锁和线程安全问题
- 12-31线程入门之start()和run()的区别
- 12-31ConcurrentHashMap允许一边遍历一边更新,而用HashMap则会报线程安全问题
- 12-31mybatis(1) SqlSessionTemplate是如何保证的MyBatis中的SqlSession的线程安全的?