volatile和synchronized的区别

volatile和synchronized特色

首先须要理解线程安全的两个方面:执行控制内存可见html

执行控制的目的是控制代码执行(顺序)及是否能够并发执行。缓存

内存可见控制的是线程执行结果在内存中对其它线程的可见性。根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操做完成后再把结果从线程本地刷到主存。安全

synchronized关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被synchronized关键字保护的代码块没法被其它线程访问,也就没法并发执行。更重要的是,synchronized还会建立一个内存屏障,内存屏障指令保证了全部CPU操做结果都会直接刷到主存中,从而保证了操做的内存可见性,同时也使得先得到这个锁的线程的全部操做,都happens-before于随后得到这个锁的线程的操做。markdown

volatile关键字解决的是内存可见性的问题,会使得全部对volatile变量的读写都会直接刷到主存,即保证了变量的可见性。这样就能知足一些对变量可见性有要求而对读取顺序没有要求的需求。并发

使用volatile关键字仅能实现对原始变量(如boolen、 short 、int 、long等)操做的原子性,但须要特别注意, volatile不能保证复合操做的原子性,即便只是i++,实际上也是由多个原子操做组成:read i; inc; write i,假如多个线程同时执行i++volatile只能保证他们操做的i是同一块内存,但依然可能出现写入脏数据的状况。app

在Java 5提供了原子数据类型atomic wrapper classes,对它们的increase之类的操做都是原子操做,不须要使用sychronized关键字。jvm

对于volatile关键字,当且仅当知足如下全部条件时可以使用:post

1. 对变量的写入操做不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
2. 该变量没有包含在具备其余变量的不变式中。优化

 

volatile和synchronized的区别

  • volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取; synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。
  • volatile仅能使用在变量级别;synchronized则可使用在变量、方法、和类级别的
  • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则能够保证变量的修改可见性和原子性
  • volatile不会形成线程的阻塞;synchronized可能会形成线程的阻塞。
  • volatile标记的变量不会被编译器优化;synchronized标记的变量能够被编译器优化
相关文章
相关标签/搜索