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

volatile与synchronized的区别

2016-08-16 17:51 176 查看

1 最根本的区别

1)       volatile是一个变量修饰符

2)       synchronized是一个方法或块的修饰符。

2 volatile的原理

一个volatile类型的变量不允许线程从主内存中将变量值拷贝到自己的存储空间,因为一个声明为volatile类型的变量将只允许每个线程对它的读写必须在内存中进行,而不能在寄存器或者CPU缓存上运行。每次线程读值的时候,必须从内存中读取数据,而写值的时候,也会保证自己修改之后,立即同步到内存中。

3 synchronized的原理

Synchronized对代码块进行多线程并行控制是通过获取和释放由监听器控制的锁(对象锁)来实现的,如果两个线程都使用一个监听器(相同对象锁),那么对象锁在任意时刻只可能由一个线程获得,这是一般的同步。另外,synchronized还能使内存同步,在实际当中,synchronized使得所有的线程内存与主内存同步,具体逻辑如下:

1)       线程从监听器获得对象锁

2)       线程内存更新所有的变量,也就是说他将读取主内存中的变量,使自己的变量保持有效。

3)       代码块执行

4)       任何变量的变更都将写回主内存中

5)       线程释放对象的锁给监听器。

所以volatile只能在线程内存和主内存之间同步一个变量的值,而synchronized则同步在线程内存和主内存之间所有变量的值,并且通过锁住和释放监听器来实现,显然,synchronized在性能上将比volatile更加有所消耗。

4 使用中的区别

1)       volatile本质上在告诉JVM当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程将被阻塞住。

2)       volatile仅能使用在变量级别,synchronized则可以使用在变量、方法和类级别的。

3)       volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性

4)       volatile不会造成线程阻塞,synchronized可能造成线程阻塞。

5)       volatile标记的标量不会被编译器优化,synchronized标记的代码块可以被编译器优化。

5 volatile注意事项

Volatile修饰关键字的时候,需要注意以下两点:

1)       对volatile修饰的变量A,当对这个变量 A的值是由自身的上一个决定时,比如A=A+1或者A++等,volatile关键字失效。

2)       只有当变量和相应操作的值和本身无关的时候,才是原子级别的操作。

3)       long与double的赋值,都不是原子操作,要在线程间共享long或者double字段时,必须在synchronized中操作。

6 synchronized注意事项

1)       两个并发线程访问同一个对象object的synchronized(this)同步代码块,一个时间内只能有一个线程得到执行,另一个线程必须等待。

2)       一个线程访问object的synchronized(this)同步代码块时,另一个线程仍然可以访问该object的非synchronized(this)同步代码块。

3)       一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁,结果,其他线程对该object对象的所有同步代码块的访问都会被阻塞。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java