一、HappenBefore指令重排
-
概念:执行代码的顺序可能和编写的代码不一致,即虚拟机优化代码顺序,则为指令重排,即编译器为了优化程序性能而采取的对指令进行重新排序执行的一种手段。
-
程序执行步骤:
1、从内存中获取指令
2、将指令解码翻译
3、从寄存器拿值
4、操作
5、写回。
-
原因:当一条指令非常耗时间的时候,其下面的指令和该指令没有关系,则系统会自动优化代码执行顺序,先执行下面的代码。
-
数据依赖:编译器和处理器在重新排序时候,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。
-
发生情况:硬件层面、虚拟机层面
二、volatile保证可见性
- 可以看作是实现了synchroniz的一部分功能,保证了数据的透明性。可以避免指令重排的现象。
- 下面代码如果不加上volatile的话程序将会一直在循环中,没有时间来将num从工作内存写到主内存中去,加上之后会立刻写道主内存,因此程序只执行1s。
private volatile int num=0;
new Thread(()->{
while(num==0);
}).start()
Thread.sleep(1000);
num=1;
三、可重入锁ReentrantLock
- 概念:如果某个线程试图获取一个已经由他自己持有的锁时,那么这个请求会立刻成功,并且会将这个锁的计数值加1,当线程退出同步代码块时,计数器将会递减,等于0时候锁释放。
ReentrantLock lock = new ReentrantLock();
public void a() throws InterruptedException {
lock.lock();
System.out.println(lock.getHoldCount());
doSomething();
lock.unlock();
System.out.println(lock.getHoldCount());
}
四、CAS比较并交换
