线程---操作系统内存模型、java内存模型、线程可见性问题、 指令重排序、Happens-before规则
作者:互联网
操作系统内存模型
- L1、L2是每个CPU自己的高速缓存
- L3是CPU之间共享的缓存
- L1和L2的缓存命中率均约为80%
- 达到L3缓存数据占比4%左右
Java内存模型
- 每个线程有自己的工作内存
- 工作内存包含线程本地局部变量和主内存的副本拷贝
- 线程之间的共享变量通过主内存在各线程间同步
线程可见性问题
package day0201;
public class ThreadSafe {
private static int a=0;
public static void main(String[] args) throws Exception {
Thread threadA = new Thread(() ->{
System.out.println("threadA"+Thread.currentThread().getName()+"a="+a);
a=1;
System.out.println("threadA"+Thread.currentThread().getName()+"a="+a);
});
Thread threadB = new Thread(()->{
System.out.println("threadB"+Thread.currentThread().getName()+"a="+a);
a=1;
System.out.println("threadB"+Thread.currentThread().getName()+"a="+a);
});
threadA.start();
threadB.start();
threadA.join();
threadB.join();
System.out.println("a="+a);
}
}
结果:
- 线程工作内存的值写入到主内存,另一个线程从主内存读取到这个值
- 由于可见性问题,另一个线程拿到的值并不是实时的
指令重排序问题
package day0201;
public class ThreadRecordering {
private static int a=0;
private static int b=0;
private static int x=0;
private static int y=0;
public static void main(String[] args) throws Exception {
Thread threadA = new Thread(()->{
b=1;
x=a;
});
Thread threadB = new Thread(()->{
a=1;
y=b;
});
threadA.start();
threadB.start();
threadA.join();
threadB.join();
System.out.println("x="+x+";y="+y);
}
}
结果,x=0;y=1或x=1;y=0或x=0;y=0或x=1;y=1(都有可能)
重排序可能发生再编译器,也可能发生再处理器
重排序发生的条件
违反了Happens-before规则,就会发生指令重排序
Happens-before规则
- 程序次序规则:在程序中若操作A先于操作B发生,那么线程中操作A也先于操作B发生
- 对象终结规则:一个对象的构造函数的完成先行发生于其finalize()方法
- 锁规则:对同一个锁,加锁操作先行发生于解锁操作
- 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则操作A先行发生于操作C
- volatile变量规则:对一个volatile变量的写操作先行发生于对这个变量的读操作
- 线程启动规则:Thread对象的start()方法先行发生于此线程中的每个指令操作
- 线程中断规则:一个线程对另一个线程调用interrupt()方法,先行发生于被中断线程检测到中断时间
- 线程结束规则:线程中所有的操作都先行发生于线程的终止时,如线程结束,Thread.join()返回
标签:Thread,threadA,模型,线程,内存,操作,threadB 来源: https://blog.csdn.net/weixin_45335305/article/details/104131505