在聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响 我们了解了处理器缓存一致性协议的原理,并且提到了它对并发编程的影响,“多个线程对同一个变量一直使用CAS操作,那么会有大量修改操作,从而产生大量的缓存一致性流量,因为每一次CAS操作都会发出广播通知其他处理器,从而影响程序的性能。”
这一篇我们通过两种实现自旋锁的方式来看一下不同的编程方式带来的程序性能的变化。
先理解一下什么是自旋,所谓自旋就是线程在不满足某种条件的情况下,一直循环做某个动作。所以对于自旋锁来锁,当线程在没有获取锁的情况下,一直循环尝试获取锁,直到真正获取锁。
在聊聊高并发(三)锁的一些基本概念 我们提到锁的本质就是等待,那么如何等待呢,有两种方式
1. 线程阻塞
2. 线程自旋
阻塞的缺点显而易见,线程一旦进入阻塞(Block),再被唤醒的代价比较高,性能较差。自旋的优点是线程还是Runnable的,只是在执行空代码。当然一直自旋也会白白消耗计算资源,所以常见的做法是先自旋一段时间,还没拿到锁就进入阻塞。JVM在处理synchrized实现时就是采用了这种折中的方案,并提供了调节自旋的参数。
这篇说一下两种最基本的自旋锁实现,并提供了一种优化的锁,后续会有更多的自旋锁的实现。
首先是TASLock (Test And Set Lock),测试-设置锁,它的特点是自旋时,每次尝试获取锁时,采用了CAS操作,不断的设置锁标志位,当锁标志位可用时,一个线程拿到锁,其他线程继续自旋。
缺点是CAS操作一直在修改共享变量的值,会引发缓存一致性流量风暴
package com.test.lock;
// 锁接口
public interface Lock {
public