一、volatile
volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。
二、volatile 的特性
①保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)
class ThreadVolatileDemo extends Thread {
//不用volatile修饰flag的话,虽然主线程中设置flag为
//false,也不会使程序停止运行,因为 threadVolatileDemo子线程
//一直读取的是本地内存(主内存没将flag还是true的副本),这样子
//线程一直在执行while循环。
//使用Volatile关键字将强制线程每次读取该值的时候都去主内存中取值
public volatile boolean flag = true;
@Override
public void run() {
System.out.println("开始执行子线程....");
while (flag) {
}
System.out.println("线程停止");
}
public void setRuning(boolean flag) {
this.flag = flag;
}
}
public class ThreadVolatile {
public static void main(String[] args) throws InterruptedException {
ThreadVolatileDemo threadVolatileDemo = new ThreadVolatileDemo();
threadVolatileDemo.start();
Thread.sleep(3000);
threadVolatileDemo.setRuning(false);
System.out.println("flag 已经设置成false");
Thread.sleep(1000);
System.out.println(threadVolatileDemo.flag);
}
}
②禁止进行指令重排序。(实现有序性)
③volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。
class VolatileNoAtomic extends Thread {
private static volatile int count = 0;
@Override
public void run() {
//每个线程给共享资源count加1000
for (int i = 0; i < 1000; i++) {
count++;
}
System.out.println(getName() + "-----" + count);
}
}
public class Demo001{
public static void main(String[] args) {
// 初始化10个线程
VolatileNoAtomic[] volatileNoAtomic = new VolatileNoAtomic[10];
for (int i = 0; i < 10; i++) {
// 创建
volatileNoAtomic[i] = new VolatileNoAtomic();
}
for (int i = 0; i < volatileNoAtomic.length; i++) {
volatileNoAtomic[i].start();
}
}
}
使用开发包中的atomic解决:
class VolatileNoAtomic extends Thread {
//private static volatile int count = 0;
private static AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
//每个线程给共享资源count加1000
for (int i = 0; i < 1000; i++) {
//count++;
count.incrementAndGet();//就相当于count++
}
System.out.println(getName() + "-----" + count);
}
}
public class Demo001{
public static void main(String[] args) {
// 初始化10个线程
VolatileNoAtomic[] volatileNoAtomic = new VolatileNoAtomic[10];
for (int i = 0; i < 10; i++) {
// 创建
volatileNoAtomic[i] = new VolatileNoAtomic();
}
for (int i = 0; i < volatileNoAtomic.length; i++) {
volatileNoAtomic[i].start();
}
}
}