文章目录
自旋锁指多线程下,当一个线程尝试获取锁的时候,如果锁被占用,则在当前线程循环检查锁是否被释放,此时当前线程并没有休眠或挂起。
1. 锁
在前面提到了synchronized关键字,其也是Java实现的一种锁机制,但本人认为其并不能实现广义锁的多种特性(公平性、乐观性等),因此将锁的介绍放在此处。
通常情况下,锁用来将某个对象或某段代码标记,使得JVM在程序执行时根据锁的状态来实现特定操作,而锁的状态由分为很多种,并且也能从不同的角度来讨论锁。
1.1 自旋锁与互斥锁
- 自旋锁:尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁
- 优点是减少线程上下文切换的消耗,因为线程不会阻塞,也就不会产生内核态和用户态的切换
- 缺点是长时间循环获取会无谓的CPU消耗
- 互斥锁:线程获取资源前必须获得该资源的锁,否则无法操纵资源
- 优点是确保了资源能被某线程安全的访问
- 缺点是可能造成死锁,且加锁/解锁开销较大
1.2 乐观锁与悲观锁
- 乐观锁:认为读多写小,遇到并发写的可能性低。指对资源的访问不会上锁,而在更新前判断在操作过程中有没有线程已经更新过此数据
- 悲观锁:认为读少写多,遇到并发写的可能性高。在访问资源时一定会对资源上锁,其他线程在锁释放之前无法访问
1.3 公平锁与非公平锁
我们知道多线程下必然存在某个线程在执行,多个线程在等待(就绪态),在线程执行完毕后等待线程中出现一个线程执行,而根据挑选的原则,将锁分为公平锁和非公平锁
- 公平锁:就绪队列中的线程按照申请锁的顺序来获取锁(等待时间长短)
- 非公平锁:与公平锁不同。JVM按照随机、就近原则给等待线程分配锁
1.4 共享锁与独占锁
- 独占锁:指某个线程独占一个锁,独占期间其他线程无法访问,是一种悲观锁,互斥锁就是独占锁的一种实现
- 共享锁:指允许多个线程共享某资源,是一种乐观锁
1.5 分段锁
分段锁是一种设计思想,通过对要访问的内存分段进行加锁来实现粒度更小的保护。
比如在Java1.7的ConcurrentHashMap实现中就利用了分段锁。
ConcurrentHashMap内部通过数组+链表时间,当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。
2. 自旋锁基础之CAS自旋
2.1 CAS介绍
Compare And Swap ========>compareAndSwapInt,它是一条CPU并发原语。它的功能时判断内存的某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。
系统原语: 由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行不能被打断。
2.2 CAS的优缺点
- CASS是一种乐观锁,其具有非阻塞性,对死锁问题天然免疫,在高并发下,比其他锁有更好的实现
- 一般情况下开销更小,但可能存在饥饿现象(线程数较多,等待时间长)
- ABA问题:A变成B再变成A,解决方案有
- 版本号
- 使用JDK1.5后的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。(还是版本号)
- 只能保证一个共享变量的原子操作:但从Java1.5开始 JDK 提供了 AtomicReference类 来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作。
3. AQS
AbstractQueuedSynchronizer(AQS)这个抽象类,是Java并发包 java.util.concurrent 的基础工具类,是实现 ReentrantLock、CountDownLatch、Semaphore、FutureTask 等类的基础,实现了除了java自带的synchronized关键字之外的锁机制
3.1 AQS的核心思想
如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进 入等待队列,等待被唤醒。
3.2 CLH锁
CLH锁是基于链表实现的自旋锁,它不断的轮询前驱的状态,如果前驱释放锁,它就结束自旋转。
CLH锁实现如下:
- 线程持有自己的node变量,node中有一个locked属性,tru