回答
能,一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。
原子性
Java中的原子操作 所谓原子操作,就是"不可中断的一个或一系列操作" , 在确认一个操作是原子的情况下,多线程环境里面,我们可以避免仅仅为保护这个操作在外围加上性能昂贵的锁,甚至借助于原子操作,我们可以实现互斥锁。 … 原子性可以应用于除long和double之外的所有基本类型之上的“简单操作”。
NOTICE
volatile并不完全具有原子性,对于复合操作其仍存在线程不安全的问题,如
package cn.caeser.volatiletest;
public class VolatileDemo{
private long value;
public void incre(){
value ++;
System.out.println(value);
}
public static void main(String[] args) {
final VolatileDemo volatileDemo = new VolatileDemo();
for(int i = 0; i < 10; i ++){
new Thread(new Runnable() {
public void run() {
volatileDemo.incre();
}
}).start();
}
}
}
每次执行结果都可能不一样
1
3
4
2
1
5
6
7
9
8
如果需要保证其原子性,保证其线程安全,就是给 incre 方法加锁 lock/synchronized
Synchronized与volatile区别
- volatile只能修饰变量,synchronized可以修饰变量,方法以及代码块
- volatile在多线程中不会存在阻塞问题,synchronized会存在阻塞问题
- volatile能保证数据的可见性,但不能完全保证数据的原子性,synchronized即保证了数据的可见性也保证了原子性
- volatile解决的是变量在多个线程之间的可见性,而sychroized解决的是多个线程之间访问资源的同步性
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦