二、volatile 最轻量的同步机制
volatile 保证了不同线程对这个变量可见性,即一个线程对变量进行修改,其他线程就立即可见。
但是volatile 不保证变量的原子性,所以它适合的场景是一写多读。如果出现了多写的情况那么就会出现线程安全问题。
可见性测试
/**
* volatile 可见性测试
*
* @author asus
*
*/
public class VolatileReadTest {
private static int count;
private volatile static boolean flag; // 若去除volatile 关键字则end count 无法答应
public void incCount() {
count++;
}
static class MyThread extends Thread {
private VolatileReadTest write;
public MyThread(VolatileReadTest write) {
this.write = write;
}
public void run() {
System.out.println("开始执行 myThread run");
while (!flag) ;
System.out.println("end count="+count);
}
}
public static void main(String[] args) throws InterruptedException {
VolatileReadTest write = new VolatileReadTest();
new MyThread(write).start();
/*
* 主线程休眠一秒,myThread 线程阻塞在while(!flag);
* 若flag 变量修饰了volatile 则while(!flag);为假 跳出死循环
*
* 若不增加Thread.sleep(1000); 和flag 不修饰volatile变量,由于main线程执行的flag=true 在while(!flag);
* 之前所以while(!flag);为假 跳出死循环
*
* 具体使用需要开发人员自己好好体会
* */
Thread.sleep(1000);
count = 10086;
flag = true;
Thread.sleep(1000);
System.out.println("main end count= "+count);
}
}
多写测试
/**
* volatile 多写测试
*
* @author asus
*
*/
public class VolatileWriteTest {
private volatile int count;
public void incCount() {
count++;
}
static class MyThread extends Thread {
private VolatileWriteTest write;
public MyThread(VolatileWriteTest write) {
this.write = write;
}
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10000; i++) {
write.incCount();
}
}
}
static class MyThread2 extends Thread {
private VolatileWriteTest write;
public MyThread2(VolatileWriteTest write) {
this.write = write;
}
public void run() {
for (int i = 0; i < 10000; i++) {
write.incCount();
}
}
}
public static void main(String[] args) throws InterruptedException {
VolatileWriteTest write = new VolatileWriteTest();
new MyThread(write).start();
new MyThread2(write).start();
Thread.sleep(1000);
System.out.println(write.count); //理想值是20000
}
}