1 . volatile 简述
volatile 可以认为是程度较轻的synchronized,volatile编码较少,并且运行时,效率较高,但它只是synchronized功能的一部分。
volatile 禁止指令重排,且将修改后的数据,立即从工作内存中刷新到主内存中。
缺点:
volatile变量是轻量级的同步机制,因为在使用这些变量时不会发生上下文切换或者线程调度等操作。然而,volatile变量同样存在一些局限性:虽然它提供了相似的可见性保证操作,但不能用于构建原子的复合操作。因此,当一个变量依赖于其他变量时,或者变量的新值依赖与旧值时,就不能使用volatile变量;计算器或者互斥体就不能使用。
2. volatile 与 synchronized 对比
性能上比较:volatile 性能更优
volatile 不持有对象锁,synchronized持有对象锁
volatile并发执行,synchronized 顺序执行
volatile 通过禁止指令重排,synchronized通过只有一个线程执行,单线程不存在指令重排
3. volatile 的使用条件
正确使用volatile要满足两个条件:
对变量的写操作,不依赖于当前值,如:计数器就不适用volatile
该变量没有包含在具有其他变量的不变式中
public class Stack {
public static void main(String[] args) {
Sum sum = new Sum();
ThreadTest1 s = new ThreadTest1(sum);
for (int i = 0; i < 1000; i++) {
new Thread(s).start();
}
System.out.println(sum.sum);
}
}
class ThreadTest1 implements Runnable {
private Sum sum;
public ThreadTest1(Sum sum) {
this.sum = sum;
}
public void run() {
sum.setSum();
}
}
class ThreadTest2 implements Runnable {
private Sum sum;
public ThreadTest2(Sum sum) {
this.sum = sum;
}
public void run() {
sum.getSum();
}
}
class Sum {
public volatile Integer sum = 0;
public void setSum() {
sum++;
System.out.println(sum);
}
public Integer getSum() {
return sum;
}
}
</pre><p></p><p></p><p>4. volatile 使用场景</p><p><span style="white-space:pre"> </span>4.1 状态标记</p><p><pre name="code" class="java">public class State {
private volatile boolean state = true;
public void shutdown() {
this.state = false;
}
public void doSomething() {
if (state) {
System.out.println(Thread.currentThread().getName()
+ ": I'm running");
}
}
public static void main(String[] args) {
State s = new State();
for (int i = 0; i < 10; i++) {
new Thread(new Thread2(s)).start();
if (i == 2) {
new Thread(new Thread1(s)).start();
}
}
}
}
class Thread1 implements Runnable {
private State state;
public Thread1(State state) {
this.state = state;
}
public void run() {
state.shutdown();
}
}
class Thread2 implements Runnable {
private State state;
public Thread2(State state) {
this.state = state;
}
public void run() {
state.doSomething();
}
}
4.2 独立观察
此种情况是只有一个线程对数据进行修改,多个线程读取修改后的值。
例如,天气情况,一个线程修改当前的天气情况,其他线程读取天气信息。
4.3 volatile与synchronized的读写锁使用,提高效率
public class ReadWrite {
volatile int value = 0;
public int getValue() {
return value;
}
public synchronized void increment() {
value++;
}
}
4.4 单例模式,双重锁检查
public class Singleton {
volatile private static Singleton singleton;
private Singleton() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new ThreadTest()).start();
}
}
}
class ThreadTest implements Runnable {
public void run() {
Singleton s = Singleton.getInstance();
System.out.println(s);
}
}
参考资料
IBM: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
《java并发编程实战》