java线程同步volatile与synchronized(二)
来源:互联网 发布:知乎健身的变化女生 编辑:程序博客网 时间:2024/05/17 22:03
前段时间面试时遇到这样一个问题:使用volatile修饰int型变量i,多个线程同时进行i++操作,这样可以实现线程安全吗?
我感觉是不可以的,但是又说不出来为什么。下来后翻看了许多资料,终于了解了volatile的含义和用法了,一起来看看吧。
volatile是变量修饰符,其修饰的变量具有可见性。在Java中为了加快程序的运行效率,对一些变量的操作通常是在寄存器或是cpu缓存上进行的,之后才会同步到内存中,而加了volatile修饰符的变量则是直接读写内存。可见性也就说一旦某个线程修改了该变量,其他线程读值时可以立即获取修改之后的值。
synchronized则作用于一段代码或方法,使用了该修饰符既可以保证可见性,也能够保证原子性。可见性表现在虽然其修饰的代码段或方法里面的读写操作可能在cpu缓存上进行的,不过在出代码段或方法前会把缓存中的数据同步到内存中。原子性表现在要么不执行,要么执行到底。
x = 10; //语句1
y = x; //语句2
x++; //语句3
x = x + 1; //语句4
这四个语句哪些是原子操作?其实只有语句1是原子操作,怎么样,想不到吧?^^下面我来解释下
语句1就是1个动作,把10写入到内存。
语句2两个动作,先读取x的值,然后再写入内存。
语句3,4是一样的,有三个动作,读取x的值,计算,写入内存。
知道了这些,那么开头的问题就好理解了,比如有两个线程A和B对volatile修饰的i进行++操作,i的初始值是0,A线程执行i++时刚读取了i的值0,就切换到B线程了,B线程(从内存中)读取i的值也为0,然后就切换到A线程继续执行i++操作,完成后i就为1了,接着切换到B线程,因为之前已经读取过了,所以继续执行i++操作,最后的结果i就为1了。
从这里可以看出volatile虽然具有可见性但是并不能保证原子性。
volatile一般是用来作为状态标志的,看个我在java中如何结束线程 一文中举的例子:
使用synchronized主要是用来保证线程安全的,看一个经典的单例模式(双重校验锁):
synchronized的另一种用法是这样的(懒汉模式):
(哇塞volatile跟synchronized同台了耶!)
最后再来两篇扩展,写的都很棒!
1、volatile关键字解析,从内存模型,并发中的关键概念,讲到volatile的使用场景点击打开链接
2、多线程同步的五种方法点击打开链接
0 0
- java线程同步volatile与synchronized(二)
- Java线程篇(二):线程同步(synchronized和volatile)
- Java线程(二)----线程同步synchronized和volatile
- Java多线程(二):线程同步synchronized和volatile
- java线程同步volatile与synchronized
- java线程同步volatile与synchronized
- java线程同步volatile与synchronized(一)
- java线程同步volatile与synchronized(三)
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Device Tree中的.dts和dtsi文件介绍
- 史上最易懂的Android jni开发资料--NDK环境搭建
- leecode 解题总结:114. Flatten Binary Tree to Linked List
- 用服务器日志监控软件、服务器日志分析工具软件教你如何查看服务器日志?
- 完美实现table带边框效果边框
- java线程同步volatile与synchronized(二)
- 找出值最大的行号和列号
- [luoguP3599]Koishi Loves Construction
- HiveQL:视图
- NumberUtils、ArrayUtils和RandomUtils工具类用法
- equals()、hashCode()方法
- TK联发科MTK8735 核心板4G 全网通4核64位 物联网方案LTE模块 MTK 3G/4G行业设备解决方案
- Xcode如何编写C++
- JDBC中日期时间的处理技巧