volatile的使用原则
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/SJQ。
http://www.cnblogs.com/shijiaqi1066/p/4352802.html
volatile关键字
对于普通变量,在一个线程中更新变量值,则在其他线程中该变量的值并不会改变(存在时间差)。如果需要在其他线程中立即可见,需要使用 volatile 关键字。volatile 不能代替锁,一般认为volatile 比锁性能好(不绝对)。
例:两条线程,使用一个标志用于控制一条线程的循环,该标志由另一条线程进行操作。即一条读,一条写。若该标志没有被volatile修饰,则线程中循环永远无法结束。
public class TestMain { static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { while (flag) {} System.out.println(Thread.currentThread().getName() + "线程停止,死循环被打开"); } }).start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } flag = false; System.out.println(Thread.currentThread().getName() + "修改flag为" + flag); } }).start(); Thread.sleep(Integer.MAX_VALUE); } }
例:(书上的例子)通过一个程序理解volatile。使用-server 的JVM 运行该程序,若没有使用volatile则程序中while永远无法停止。VolatileStopThread只会在自身线程内存中查看stop的值,永远不会更新。
public class VolatileStopThread extends Thread { private volatile boolean stop = false; public void stopMe() { stop = true; System.out.println("stop = " + stop); } public void run() { int i = 0; while (!stop) { i++; } System.out.println("Stop thread"); } public static void main(String args[]) throws InterruptedException { VolatileStopThread t = new VolatileStopThread(); t.start(); Thread.sleep(1000); t.stopMe(); Thread.sleep(1000); } }
volatile的使用原则
理解volatile关键字是熟悉Java并发编程的必经之路。如果要彻底理解volatile,首先需要理解Java内存模型。
volatile是java提供的一个轻量级的同步机制,用来对被修饰的变量进行同步。
使用volatile修饰的变量会对多个线程可见,也就是说任何线程都可以看到被volatile修饰的变量的最终值。
volatile并不能替代synchronized,因为volatile只提供了可见性,并没有提供互斥性;在多线程并发修改某个变量值时,依然会出现并发问题。
所以volatile最适合用的场景是一个线程修改被volatile修饰的变量,其他多个线程获取这个变量的值。
当多个线程并发修改某个变量值时,必须使用synchronized来进行互斥同步。
关于volatile的性能
若一个变量用volatile修饰,那么对该变量的每次读写,CPU都需要从主内存读取,性能肯定受到一定影响。
也就是说:volatile变量远离了CPU Cache,所以没那么高效。
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/SJQ。
http://www.cnblogs.com/shijiaqi1066/p/4352802.html