StampedLock是JDK1.8新引入的锁机制,可以简单的理解为读写锁的改进版本。我们知道读写锁可以让读和读之间完全并发,但是读和写之间是有阻塞的。StampedLock使用了一种乐观锁的读策略,这种机制类似于无锁的概念,使得获取锁的过程中不会阻塞写线程。
简单例子
下面给出一个JDK官方给的Demo:
上面是一个点移动的一个抽象。首先对于move()操作,加锁和解锁的过程和普通的Lock类似。对于distanceFromOrigin(),首先会使用tryOptimisticRead()加一个乐观读锁,此时会返回一个stamp数值。获取到X和Y的值之后,去验证其有效性,如果尚未被修改过,那么读取成功,计算结果返回。如果验证失败,那么会加读锁。
在这个例子中,使用的锁升级,里面调用了readLock()方法去操作。这个操作会有一个循环的CAS操作,直到获取到锁为止。
StampedLock的缺陷
在使用StampedLock的过程中,如果API使用的不当,则有可能造成CPU占用率过高。
StampedLock在使用readLock()的时候,使用的是Unsafe.park()函数。park()在遇到线程中断时,会直接返回。这就导致阻塞在park()上面的线程被中断后,会再次进入循环,从而导致CPU的大量占用。以下是事例代码:
笔者在自己的电脑上面测试时,CPU的占用率如下:
参考:《Java高并发程序设计》