package com.itheima._4volatile;
public class MyThread2 extends Thread{
public static volatile int money = 0;//volatile 不能让变量是一个原子操作了
@Override
public void run() {//run方法不让抛异常throws//父类和子类异常最好保持一致
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(10);//休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
money++;
}
}
}
package com.itheima._4volatile;
import com.itheima._3非原子性.MyThread;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
MyThread my = new MyThread();
my.start();
for (int i = 0; i < 100; i++) {
Thread.sleep(10);//两个线程总共 花费时间是1秒
MyThread.money++;
}
//等待(休眠)2秒 输出结果
Thread.sleep(5000);
System.out.println("总额:"+MyThread.money);//总额:146
}
}
Volatile
1. 解决非可见性的问题
原理:
加了volatile的变量,一旦修改强制变量副本失效
各个使用该变量的线程,重新获取主内存的新值
public static volatile int a = 1;//加上volatile关键字就可以了2. 解决非有序性的问题
原理:
不会让编译的字节码文件进行重排。
不会造成由重排所导致的数据不一致情况。
3. 不能解决非原子性的问题
无法解决原子操作问题
i++是不是原子操作 ?
/* i++ 不是一个原子操作;也就是说i++不是一个整体,不是不可分割,它是分三步: */ 1. 获取 i的值 2. i + 1 3. i + 1 后的值 赋值给 i //以上每一步都有可能失去cpu执行权,被其他线程抢过去