一、内存模型
1、线程分配内存空间:
每一个线程都有自己的内存和主内存独立;工作空间存储的主内存中变量的副本。
2、线程与主内存之间数据的传递过程
主内存拷贝工作内存存储:
1、当主内存执行的读read操作;
2、工作内存执行load操作
反之:
1、工作内存执行的存储store操作
2、主内存执行的相应的写write操作
出现线程之前数据不一致的问题如何解决: 出现了可见性
一个线程修改了一个变量,其他线程收到通知立即更新工作线程值。如何实现
1、 volatitle
2、synchronized
3、final
注意:
就算用volatile修饰只能保证线程之间的可见性,不能保证线程之间的原子性,如果要解决上面的问题一般使用JDK自带的AQS
有序性:
在单线程下面,操作都是有序的;但是在多线程,同时执行共享内存的代码
指令不一定有序,有可能会出现指令重排序。
什么是指令重排序?
单线程
线程内串行(读、写之间的组合)语义编译器不考虑多线程的语义
多线程
在线程指令会发生重排序例如:
// TODO
一般出现这种问题都是采用读写分离、加锁。
指令重排序原则
- 单线内部都是串行
- volatitle: volatile写,先发生于读。
- 锁规则: 解锁必然发生在随后的加锁之前。
- 传递性: 推导方式
- 线程所有的锁先于线程的终结(Thread.join)
- 线程的中断interrupt先于中断线程的代码
- 对象的构造函数执行由于finalize代码
解释运行
解释执行以解释的方式运行字节码。
编译运行(JIT)
将字节码编译成二进值(机器码);直接执行二进制文件;运行后性能有数量级的提升