Volatile
Volatile是什么?
volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色。同synchronized相比(synchronized通常称为重量级锁),volatile更轻量级,相比使用synchronized所带来的庞大开销,倘若能恰当的合理的使用volatile,自然是美事一桩
有以下的特性:
而普通变量无法做到立即感知这一点,变量的值在线程之间的传递均需要通过主内存来完成,比如,线程A修改了一个普通变量的值,然后向主内存回写,另外一条线程B只有在线程A的回写完成之后再从主内存中读取变量的值,才能够读取到新变量的值,也就是新变量才能对线程B可见。
java内存模型规定,volatile变量的每次修改都必须立即回写到主内存中,volatile变量的每次使用都必须从主内存刷新最新的值。
普通变量仅仅会保证在该方法的执行过程中所有依赖赋值结果的地方都能获得正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致,因为一个线程的方法执行过程中无法感知到这点,这就是“线程内表现为串行的语义”。
volatile关键字可以保证可见性和有序性,那么volatile是不能保证原子性
比如a++
总结
(1)volatile关键字可以保证可见性;
(2)volatile关键字可以保证有序性;
(3)volatile关键字不可以保证原子性;
(4)volatile关键字的底层主要是通过内存屏障来实现的;
(5)volatile关键字的使用场景必须是场景本身就是原子的;
使用
public class ListAdd1 {
private volatile static List list = new ArrayList();
public void add(){
list.add("bjsxt");
}
public int size(){
return list.size();
}
public static void main(String[] args) {
final ListAdd1 list1 = new ListAdd1();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
for(int i = 0; i <10; i++){
list1.add();
System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
if(list1.size() == 5){
System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
throw new RuntimeException();
}
}
}
}, "t2");
t1.start();
t2.start();
}
}