并发编程的尝试之volatile的困惑

去年在使用C++实现一个线程安全的HashMap时,当我实现了HashMap,准备引入锁时,面对这么多共享的变量,我竟一时不知那些变量该使用volatile去声明,volatile一个在我大学毕业前就自认为搞的烂透的一个概念,当有人问我volatile时,我会从GCC编译器是如何实现volatile的,再到CMP,SMP,架构下CPU是如实现数据的可见性,及缓存一致性协议,内存栏栅。但在二年后的去年六七月份,当我真正想实现一个在多线程并发环境中使用的HashMap时,我却不知道该如何去使用它

有道是 纸上得来终觉浅,决知此事需躬行,不躬不知道,一躬吓一跳,原来我真的是只会与别人夸夸其谈,纸上谈兵的一个渣渣,一个垃圾,只会吹吹牛逼罢了

 

当时的我感觉并发编程实在是太难了,太难了,像我这种渣渣还是老老实实写写业务BUG,改改配置吧!我的自信心也因此倍受打击,因此并发编程大业无疾而终,唯留那残缺的代码独自躺在乌班图的虚拟机中

 

最近在了解到Java的volatile实现时,我脑子里,第一个蹦出来的疑问就是为什么JMM只要保证在JVM中各个Java字节码解释器线程栈中的副本变量(工作内存)与,主内存中的变量同步,就可以保证,共享变量的可见性,而完全不用关心每颗物理CPU核心的寄存器,一级cache,二级cache,共享的三级cache中的值有没有回写到内存中?JVM完全无视了硬件层次的数据一致性,而C/C++中的volatile保证的是一个变量在从内存通过3,2,1级cache到达cpu寄存器进行运算后要马上回写到内存,下次运算时再从内存中获取,这期间会被cacheline cache住,由membar及缓存一致性协议来保证cacheline中的数据对其它核心及其它cpu的可见性

 

我反编译了一段使用volatile修饰的int类型的Java代码,把反编译的字节码指令,对着JVM解释器源码,一个一个的查看JVM是怎样用C++中的volatile实现Java中使用volatile修饰的变量的,我试图在JVM解释器的C++源码中找到与volatile的相关的蛛丝马迹,但未果。于是我合上笔记本,怏怏地躺在床上打开小吊扇,对着旋转的小吊扇,我说吊扇啊,吊扇,请你告诉我?This is why

 

吊扇拖梦与我,如此,如此,这般,这般,一觉醒来,我顿悟,原来如此,,,

 

我称我的顿悟为变量对编译器的可见性或编译器对变量的可感知性,Java代码中的变量只能被Javac编译器感知到,JVM虚拟了一个的基于栈的CPU,每一个JVM解释器线程就是一颗虚拟CPU,在JVM中只需要保证volatile修饰的变量被加载到这个栈中进行运算后立刻马上同步到主内存中(同时还起membar的做用)即可保证对同一个JVM进程中各个字节码解释器线程的可见性,Java代码被编译成字节码后就是一堆相对偏移量和字节码,在被解释器,翻译成物理CPU的指令后就是另一堆相对偏移量和指令而已,Java代码是用Javac编译器编译的,JVM解释器是用C++实现的由g++编译器编译,Java代码中的一个变量是不可能被g++编译器感知到,从而把Java中的一个变量优化到物理CPU的寄存器中

我试着讲清楚但可能还是有点不清楚,因为我自己都不确定这是一个正确的说法

你可能感兴趣的:(并发编程,思考)