您的位置:首页 > 编程语言 > Java开发

Java保证共享变量“可见性”的机制

2019-06-19 15:04 225 查看

Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM(Java虚拟机),JVM执行字节码,最终转化为汇编指令在cpu上执行,Java中所使用的并发机制依赖于JVM的实现和cpu的指令。
在多线程中,有时候会遇到这种问题:当一个线程修改了共享变量时,另一个线程不知道这个变量已经被修改(数据修改不是修改原始数据,而是对拷贝的数据进行修改。)了,还是使用以前的变量(存放在一个缓存中),这就会造成某些线程看到的同一个变量的值是不一样的。共享变量的“可见性”就是针对这个问题来实现的。原理如下:

这种情况怎么解决呢?Java提供了两种解决方式:volatile的应用和synchronized的应用。

volatile的应用

如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。下面我们详细讲解具体实现:
Java代码:
instance=new singleton();  //instance是volatile变量

转换成汇编代码为:

0x01a3deld:....;
0x01a3de24:lock addl ...

我们可以看到volatile变量修饰的共享变量进行写操作时会多出第二行汇编代码。lock前缀的指令在多喝处理器下会引发两件事:

  • 将当前处理器缓存行的数据写回到内存。
  • 写回内存的操作会使其他 cpu里缓存了该内存地址的数据无效。(通过嗅探在总线上传播的数据来检查自己缓存的值是否过期了),然后从新从内存中把数据读到缓存里。

synchronized的实现原理和应用

当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。
JVM是基于进入和退出Monitor对象来实现方法同步和代码块同步,当两者实现的细节不一样: - 代码块同步是使用monitorenter和monitorexit指令实现的
- 方法同步是使用另外一种方法实现的(具体方法未知,尴尬吗!),但同样可以使用上面两个指令来实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: