1.volatile解决不可见性
package com.itheima.volatileVisible;
/*
高并发问题一_不可见性(重点)
*/
public class MyThread extends Thread{
//定义一个静态的成员变量,供所有的线程使用
public static volatile int a = 0;
@Override
public void run() {
System.out.println("Thread-0线程开始执行线程任务了,睡醒2秒钟,等待主线程先执行!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread-0线程2秒钟之后,睡醒了,把变量a的值修改为1");
/*
变量a被volatile关键字修饰
作用:当变量a的值被改变之后,会使所有的变量a的副本都失效,其他线程想要使用变量a的值,必须从新获取
*/
a=1;
System.out.println("Thread-0线程执行线程任务结束了!"+a);
}
}
package com.itheima.volatileVisible;
public class Demo01Visible {
public static void main(String[] args) throws InterruptedException {
//创建Thread的子类对象
MyThread mt = new MyThread();
//调用start方法,开启一个新的线程,执行run方法
mt.start();
//主线程在开启Thread-0线程之后,会继续执行main方法中的代码
System.out.println("主线程,执行一个死循环");
while (true){
if(MyThread.a==1){
System.out.println("主线程判断变量a的值==1,结束死循环!");
break;
}
}
}
}
主线程,执行一个死循环
Thread-0线程开始执行线程任务了,睡醒2秒钟,等待主线程先执行!
Thread-0线程2秒钟之后,睡醒了,把变量a的值修改为1
主线程判断变量a的值==1,结束死循环!
Thread-0线程执行线程任务结束了!1
2.volatile解决无序性
注意:变量添加了volatile关键字,生成class文件,就不会在进行重排了
3.volatile不能解决非原子性
package com.itheima.demo04volatileAtomic;
/*
volatile不能解决原子性
*/
public class MyThread extends Thread{
//1.定义多线程共享的静态变量money
public static volatile int money=0;
@Override
public void run() {
//2.Thread-0线程把money的值增加1000
System.out.println("Thread-0线程开始执行线程任务,增加money的值!");
for (int i = 0; i < 1000; i++) {
money++;
//增加两个线程抢夺cpu的概率
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread-0线程执行线程任务结束!");
}
}
package com.itheima.demo04volatileAtomic;
public class Demo01Atomic {
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
mt.start();
//主线程在开启新的线程之后,会继续执行main方法中的代码
//3.main线程把money的值增加1000
System.out.println("主线程开始增加变量money的值!");
for (int i = 0; i < 1000; i++) {
MyThread.money++;
//增加睡眠1毫秒的目的,是为了提高问题出现的几率
Thread.sleep(1);
}
System.out.println("主线程增加money值结束,睡眠2秒钟,等待Thread-0线程也执行完毕!");
Thread.sleep(3000);
System.out.println("最终两个线程都执行完毕,打印money的值:"+ MyThread.money);
}
}
程序执行额结果: volatile不能把原子性的三步变成一个原子执行
1).取money的值;
2).将money++
3).将money写回
这三步在执行的过程中,还是有可能把其他线程打断的
main线程改变变量money的值!
Thread-0线程开始改变money的值!
main线程改变完money的值,睡眠2秒钟,等待Thread-0线程执行完毕!
Thread-0线程执行线程任务结束了!
最终money的结果为:12233