博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
并发——关键字volatile
阅读量:6910 次
发布时间:2019-06-27

本文共 972 字,大约阅读时间需要 3 分钟。

  本段内容均来自于《Thinking in Java》并发一章的内容,作为阅读的笔记或者可以理解为抄书。

  原子性是可以用于除long和double之外的所有基本类型的“简单操作”。对于读取和写入除long和double之外的基本类型这样的操作,可以保证他们会被当做不可分割的操作来操作内存。但是对于long和double这种64位(long和double在Java中都占用64位)的数据,JVM在操作的时候会把他分成2个32位的来操作,这样在这中间就可能会发生读取和写入操作的上下文切换,从而导致看到不是你希望的结果(称为字撕裂)。当你使用volatile定义long和double的时候会获得原子性(注意在Java SE5.0之前,volatile一直没有正确的工作)。不同的JVM可以提供更强的保证,但你最好不要依赖平台性。

  volatile关键字还确保了应用中的可视性。如果你把一个域声明为volatile的,只要你对这个域做了写操作,那么所有的读取操作都能够看到这个修改。即使使用了本地缓存,情况也是如此,因为volatile域会被立即写到主存中,而读取操作就发生在主存中。

  理解原子性和易变性是不同的概念很重要,在非volatile域上的原子操作不必刷新到主存中去,因此其他读取操作也不必看到这个新值。如果多个任务同时访问一个域的话,那么这个域应该设为volatile的,或者应该使用synchronized同步方法来保护,synchronized也能将数据刷新到主存当中去。一个任务所有的写入操作对于自己本身都是可视的,所以当只有一个任务的时候就没有必要使用volatile关键字。

  当一个值依赖于他之前的值得时候(比如计算器),volatile就无法工作了。如果这个域受到其他域的限制,那么volatile也无法工作,例如Range类的lower和upper边界就必须遵循lower<=upper。

  使用volatile而不是synchronized唯一安全的的情况下就是类中只有一个可变域。再次提醒,你的第一选择应该是synchronized关键字,这是最安全的方式,而其他任何尝试都是有风险的。

转载于:https://www.cnblogs.com/xiaolong123/p/4223608.html

你可能感兴趣的文章
Go语言标准包之用io包模拟curl
查看>>
Bootstrap输入框组
查看>>
Linux下使用tcpdump进行抓包(转)
查看>>
docker 标记和推送镜像
查看>>
在弱网传输的情况下,是怎么做到节约流量的(面试小问题,Android篇)
查看>>
【转】Spring Boot特性
查看>>
Linux用户管理之使用/bin/false和/usr/sbin/nologin拒绝用户登录及其功能分析(转)...
查看>>
位置与地图(三)给地图加入覆盖层
查看>>
[CI]jenkins安装&插件管理&java-helloworld之旅
查看>>
python可变參数调用函数问题
查看>>
android多个fragment返回键层层返回
查看>>
Mapreduce实战:序列化与反序列化 int,int[],string[][]
查看>>
可执行文件格式elf和bin
查看>>
Android中获取当前位置的使用步骤
查看>>
CEF中JavaScript与C++交互
查看>>
unity3d绘画手册-------灯光之反射及各个参数解释
查看>>
深入理解程序的结构
查看>>
POJ1365 Prime Land【质因数分解】【素数】【水题】
查看>>
Java实现文件复制
查看>>
Spark修炼之道(基础篇)——Linux大数据开发基础:第三节:用户和组
查看>>