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指令实现的
- 方法同步是使用另外一种方法实现的(具体方法未知,尴尬吗!),但同样可以使用上面两个指令来实现。
相关文章推荐
- java中基本变量、对象、对象引用等在堆与栈中存储、按值传递机制、栈中对象共享机制
- Java高并发的情况下如果出现共享变量,如何保证线程安全的解决方案
- 【慕课网学习笔记】Java共享变量的可见性和原子性
- Java 多线程 变量共享
- Java初学笔记(一)变量及其内存机制
- Thinking in Java [Java编程机制] 学习笔记 -- 变量和对象
- JAVA 并发编程-线程范围内共享变量(五)
- Java中变量内存分配机制
- 栈(stack)与堆(heap)区别以及Java的string变量赋值的内部工作机制(精典转载贴)
- java基础--线程03--实现线程范围内的共享变量
- Java并发_volatile实现可见性但不保证原子性
- java线程共享变量与静态变量
- 关于python java C++ 变量机制的思考
- JAVA 反射机制 获得 private 变量
- Java中的自增操作符与中间缓存变量机制
- 2 weekend110的zookeeper的原理、特性、数据模型、节点、角色、顺序号、读写机制、保证、API接口、ACL、选举、 + 应用场景:统一命名服务、配置管理、集群管理、共享锁、队列管理
- 基于字节码指令理解Java中间缓存变量机制
- java 之 线程间变量共享
- 【Java多线程与并发库】05 线程范围内共享变量ThreadLocal
- JAVA 并发编程-线程范围内共享变量(五)