1.volatile
- 作用:保持内存的可见性
例如
import java.util.Scanner;
public class Test11 {
static class Cou {
private int flag = 0;
}
public static void main(String[] args) {
Cou c = new Cou();
Thread t1 = new Thread() {
@Override
public void run() {
while (c.flag == 0) {
}
System.out.println("循环结束");
}
};
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
Scanner sc = new Scanner(System.in);
System.out.println("随便输入一个不为0的整数");
c.flag = sc.nextInt();
}
};
t2.start();
}
}
得到的结果为
随便输入一个不为0的整数
1
并不会输出线程结束
- 在线程t1的while循环的比较操作中,先从内存中读取flag的值到cpu中,在cpu中比较flag这个值和0的相等关系
- 但是编译器判定这个逻辑循环没有干啥事,只是频繁读取内存而已,于是进行了操作优化,只是第一次真正的从内存中读取了flag,其他时候不会从内存中读取,直接从cpu中得到这个数据,于是这个t1线程永远不会结束这个循环。这也就是我们常见的编译器优化导致的线程不安全
那木如何去解决这个问题,就需要我们的volatile关键字了,就是一个线程读,一个线程写的问题。
我们给falg加上volatile关键字。
import java.util.Scanner;
public class Test11 {
static class Cou {
private volatile int flag = 0;
}
public static void main(String[] args) {
Cou c = new Cou();
Thread t1 = new Thread() {
@Override
public void run() {
while (c.flag == 0) {
}
System.out.println("循环结束");
}
};
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
Scanner sc = new Scanner(System.in);
System.out.println("随便输入一个不为0的整数");
c.flag = sc.nextInt();
}
};
t2.start();
}
}
得到的结果
随便输入一个不为0的整数
1
循环结束
- 加了volatile关键字后,我们都这个flag的操作的每一次读取都在内存上读取,就不会存在刚才所讲到的问题了。
2 .对象等待集
- 我们知道线程是的操作是抢占式执行的,我们假想有多个线程在等待一个cpu给提供资源,但是其中线程x抢cpu抢的快,但是当前cpu并没有那个可以给x提供的资源,又因为这个x不停的抢cpu,导致其他线程不能进入到cpu中,因此会影响到程序的运行效率。
为了解决这个问题,我们引入了对象等待集,也就是wait,notify,notifyAll三个关键字,要和synchronized一起用
- wait 如果cpu中没有满足这个线程执行的资源时候,让这个线程等待
- notify 当cpu中的条件成熟的时候,通知指定的线程工作,唤醒一个线程
- notifyAll 是一个唤醒所有线程,让这些线程去竞争一把锁
import java.util.Scanner;
public class Test12 {
public static void main(String[] args) {
Object o = new Object();
Thread t1 = new Thread() {
@Override
public void run() {
synchronized (o) {
try {
System.out.println("wait开始");
o.wait();
System.out.println("wait结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
Scanner scanner = new Scanner(System.in);
System.out.println("任意输出一个属,执行notify");
int x = scanner.nextInt();
synchronized (o) {
System.out.println("notify 开始");
o.notify();
System.out.println("notify 结束");
}
}
};
t2.start();
}
}
任意输出一个属,执行notify
1
notify 开始
notify 结束
wait结束
Process finished with exit code 0
本文深入探讨了Java并发编程中的Volatile关键字如何确保内存可见性,避免编译器优化带来的线程安全问题。同时,讲解了对象等待集的概念,通过Wait、Notify和NotifyAll方法解决线程间资源竞争,提升程序运行效率。
555

被折叠的 条评论
为什么被折叠?



