说下 volatile ​​ ,哈。。。。看到java有这个不得不说一下。

中山野鬼 发布于 2013/08/21 22:01
阅读 3K+
收藏 3

刚才看了个帖子,问java里的volatile。说实话,这个单词和java真格格不入。你java安心在虚拟环境下折腾就行了,包括垃圾回收,包括数据同步,该帮java程序员做好的,你就做到位,怎么还留这个小补充。。。

volatile  大意是说易变的。简单说,这个对应存储空间的值很容易被外部改变,所以编译器对于这个空间会强制从外部读取。这里有两个概念,对高级语言的程序员,但不是高级程序员需要解释的。

正常我们写个程序,运行时,操作系统会开个进程,那么大家相互独立,各忙各的事情,你的变量对应的任何空间都是根据你的函数(或方法)调用,层层展开的,这个根本不会出现易变的概念。但多线程或多进程,当可存在两个相互异步的程序执行流程,同时可能会对一个空间的数据进行读取时,那么你写入volatile则是保证,这个数据读取是最新的被别人改变的数值,同时你写出会立刻发生。你自己的一套代码不存在这个问题。

而另一个概念,从外部强制读取,实际就是从外部存储区读取,这个是由优化导致的。其实没有优化的程序,也没有volatile 的概念,它始终会从存储的位置读取数据,外面改了,自然就读到了。没必要额外增加volatile 的约束。但由于编译器存在优化,毕竟写在寄存器,比写在外设要快太多(主板上的存储区实际都是外设,和磁盘没什么区别,无非驱动方式和连接资源不一样,速度不一样)。

那么编译器会尝试对这个变量在当前计算中,只利用寄存器完成数据存储,等这个函数退出或这个空间不再被利用,或者寄存器实在不够时,才实际写到外部真正的空间中。

但这样的优化,会出现一个讨厌的事情,当这个进程被中断(你连这个不懂,如果还是计算机系毕业的,我建议你改行),那么另一个改变改数值的进程修改了这个值,就会产生逻辑错误。

volatile 对一个变量的约束,其实就是提醒编译器,对这个变量的任何读或者写操作,都需要和外部空间立刻交互。实际实现时,在这个读写过程中,还存在一个屏蔽中断的原子操作。否则机器刚好执行了计算指令,而没有做写出指令,此时被切换到另一个进程,虽然单个操作没有问题,但最后逻辑还是会乱。

正常情况下,只要不出现多个进程(线程)对同一个存储空间都有读写操作,volatile是没必要的。我惊讶于java多这个玩意想干什么?想玩多进程?你干脆再增加内嵌汇编得了。。。靠,那还要虚拟机做什么?

加载中
2
南湖船老大
南湖船老大

唠叨半天说不到重点,讲不出个所以然,偷换概念,东拉西扯。

好比说“因为1+1=2,所以你是傻逼”。前面解释volatile是对的,话锋一转,java用这个就不对,你这可真是神逻辑啊。按你的说法,女人只要负责生娃就行了,穿衣服、逛街干嘛。。尽干无关的事情。男人也是,裸体就行,穿什么衣服啊,不务正业。

大叔,别忽悠了。回去抱孙子吧。

2
gvim
gvim

java做成的事情,ibm,oracle大量使用java构造软件系统,不是说它完美,而是我们不知道它有哪些好。

volatile这样的同步原语是共享内存的必然的结果,就如同合格的C程序员都需要清楚cache一致性一样,合格的java程序员也需要清楚volatile,这个volatile是针对java体系,和C的名字相同,但目标体系不同,自然用法也不要用C的来做比较。如果这些的存在不合理的话,那么是否意味着C的内嵌汇编也做了不该做的事情?作为上层抽象语言,把汇编暴露出来做什么?把cache一致性暴露出来让C程序员考虑什么?c就弄弄数据结构,写写算法即可,这些都不需要考虑底层物理模型。

一点要清楚的是c的volatile针对物理存储共享,java的volatile针对自己arch的共享,都知道java是堆栈机而不是寄存器机,那么如果你认为java的volatile就是用来做C的事情,呃,那是你的误识,这和java有什么关系呢?volatile在C里只处理本核寄存器和外存的关系,他本来就不是为多线程,多核准备的,有volatile的时候这些功能还没出现呢,你要认为在多核环境volatile也不好,那我个人只能说你不了解它存在的意义。在io端口的定义中大量使用volatile,做嵌入式的不会这点都见得少吧。 

对于它适合做什么不适合做什么,还是市场来检验吧,java用在嵌入式里面的情况我也处理过不少,裸奔c也处理过不少,在我看来只要能上系统的地方,c都是最后一个选择。因为性能不是唯一标准,就如同程序员脑子里一提到核心竞争力一定是技术,殊不知核心竞争力构成的维度真不是单一的技术。我们需要考虑的只是性能,抽象,效率,扩展,产出这些所有因素的平衡。java本身在性能,资源,功能,产出这些选项中提供了一个被大多数认可的平衡作为参考选项。java另一个c所没有的优势是大量的工业标准,其中包括好多交互,文件等,也造就了大量和外部平台交互的企业级功能,这在任何一个生态中都是没有的,你只需要找一个功能来便可以上路。 

鞋合不合适只有上脚才能体会,java适不适合,也至少要对java有所了解吧。

1
xesam
xesam

其实吧,要谈volatile就专心谈volatile,扯上java就不应该了,更何况还是在你不精通java的情况下。

1
周翼翼
周翼翼

不明觉厉

野鬼要的就是这个效果.

周翼翼是一个良好青年, 以前以曾认真听鬼讲, 后来终于觉悟了.

1. 这个世界上的事,绝大部分可以用两句话说明主要思想

2. 凡是两句话说不明白的, 都不要说了

3. 第三句话, 啰嗦!

0
中山野鬼
中山野鬼

引用来自“南湖船老大”的答案

唠叨半天说不到重点,讲不出个所以然,偷换概念,东拉西扯。

好比说“因为1+1=2,所以你是傻逼”。前面解释volatile是对的,话锋一转,java用这个就不对,你这可真是神逻辑啊。按你的说法,女人只要负责生娃就行了,穿衣服、逛街干嘛。。尽干无关的事情。男人也是,裸体就行,穿什么衣服啊,不务正业。

大叔,别忽悠了。回去抱孙子吧。

哈哈。信不信随你了。。做java就做该java的事情,好好把软件系统做好。关心下面的东西做什么。这如同c语言里面从头到位都考虑汇编才能实现的事情一样扯淡。必须要使用到volatile的java设计目标,肯定是扯淡的设计,用别人做好的包或者基于别人的框架肯定比你自己写确实需要volatile的程序靠谱很多。

你的比方不对。如果非要用女人比方就是,既然你是受精者,而不是施精者,那就不要长小jj。不要因为想站着尿,觉得有个小jj真方便,而忘了不同性别在生殖方面的不同角色定位。简单总结,有没有小jj不是因为男人喜欢或擅长站着嘘嘘决定的。而是物种繁衍中角色定位决定的。定位搞反了,别人有的自己也想有,什么都长自己身上,那就不是生物了,是怪物。。。

0
jingshishengxu
jingshishengxu
volatile 当然很重要,多线程的java程序都指着他呢。
黑狗
黑狗
用得好的人并不多
中山野鬼
中山野鬼
回复 @jingshishengxu : 无论什么语言开发,进程都比线程设计起来方面,实话实说我是进程派,大多数的线程设计,纯粹是图省事,程序安全性很差。如果java多进程处理方便,那就把voliate去掉,这样程序员更方便。哈。还更容易保证安全性。
jingshishengxu
jingshishengxu
也真够奇葩的,在这站里看了很多搞编程的,也不是新手了,居然连一些概念都弄不清,一笔糊涂账;这再次验证我的判断,编程高手和编程老手是不同的,编程经验的积累可以让你变成老手,但却不是每个搞编程的人都能成为高手。
jingshishengxu
jingshishengxu
java以及C#的一大优势,就是给了一个多线程的解决方案,用这套方案,很容易写出多线程程序,相反,在C里面弄多线程就麻烦的多了,也困难很多。
0
迷路的游侠
迷路的游侠
你的意思是JAVA不能玩多线程?
0
typeorigin
typeorigin
虚拟机力有不逮,所以留了个小后门,哈哈
0
hawkyoung
hawkyoung

只要不出现多个进程(线程)对同一个存储空间都有读写操作,volatile是没必要的

在java里头,老土的

while(command){

dosomething

}

工作线程实现方法依然使用,这里command就要是volatile的。当然Java不同版本的内存模型对于volatile的实现好像有不同。

我印象中有人对于一些大型C工程进行统计,volatile这个关键字本身出现的概率也比其他关键字小很多,基本倒数第一

m
mononite
C里面的volatile和Java里的不是一回事,保证不了happen-before关系,用处有限,使用次数少很正常。
0
hoverlin
hoverlin
野鬼的说法我赞成,理论上说有了虚拟机,程序的细节问题应该被隐藏,但是,实际状况是留个后门,虚拟机实现上应该要简化不少,同时这个概念由于native语言在多线程开发下长期使用,大部分程序员对这个概念很了解,所以我个人到觉得到无所谓。
返回顶部
顶部