说起volatile和sychronized这两个关键字,学习过多线程的同学应该都很熟悉,在jdk1.5之前,主要就是靠这两个关键字来做多线程编程的,但在jdk1.5以后,多了一个java.util.concurrent(JUC)包,里面包含了很多工具类用于多线程编程。但今天的重点还是讲讲volatile关键字。
多线程主要就是围绕可见性和原子性这两个特性展开的,volatile关键字对应着可见性,但很多时候人们误以为使用了volatile关键字后编写多线程就没问题了,不知道它不能保证原子性。
首先来说说什么是可见性?
要说到可见性,就得扯到java内存模型了,暂且不做太多展开,简单理解下就是,现在技术的提升,使得cpu的核心数不断增多,而每个核心又拥有自己的缓存,当处理数据时会有以下几个步骤:
- 将数据从内存读取到缓存中
- 在缓存中对数据进行操作
- 将缓存中的数据写入内存中
步骤2中的操作并不是原子性,也就是在步骤1之后,如果主内存变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样
对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
正是因为这几个步骤的存在,往往别的核心从内存中读取到的数据不是最新的,这就造成了数据错误。java为了屏蔽操作系统以及硬件之间的不同,在jvm中虚拟出了一套内存模型,编码时使用volatile关键字对需要实时可见的数据修饰,在jvm底层会对该变量做特定的处理。
总结下可见性就是当多个线程操作共享数据时,保证操作的数据是最新的。
volatile关键字的作用?
刚也说过volatile关键字对应的可见性,但这是其中之一,它有两个作用:
- 1)使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据
- 2)代码底层执行不像我们看到的高级语言—-Java程序这么简单,它的执行是Java代码–>字节码–>根据字节码执行对应的C/C++代码–>C/C++代码被编译成汇编语言–>和硬件电路交互,现实中,为了获取更好的性能JVM可能会对指令进行重排序,多线程下可能会出现一些意想不到的问题。使用volatile则会对禁止语义重排序,当然这也一定程度上降低了代码执行效率
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。