这种将乐观读升级为悲观读锁的方式相比一直使用乐观读的方式更加合理 , 如果不升级为悲观读锁 , 则程序会在一个循环中反复执行乐观读操作 , 直到乐观读操作期间没有线程执行写操作 , 而在循环中不断的执行乐观读会消耗大量的CPU资源 , 升级为悲观读锁是更加合理的一种方式 。
StampedLock实现思想StampedLock内部是基于CLH锁实现的 , CLH是一种自旋锁 , 能够保证没有“饥饿现象”的发生 , 并且能够保证FIFO(先进先出)的服务顺序 。
在CLH中 , 锁维护一个等待线程队列 , 所有申请锁 , 但是没有成功的线程都会存入这个队列中 , 每一个节点代表一个线程 , 保存一个标记位(locked) , 用于判断当前线程是否已经释放锁 , 当locked标记位为true时 , 表示获取到锁 , 当locked标记位为false时 , 表示成功释放了锁 。
当一个线程试图获得锁时 , 取得等待队列的尾部节点作为其前序节点 , 并使用类似如下代码判断前序节点是否已经成功释放锁:
while (pred.locked) {//省略操作 }
只要前序节点(pred)没有释放锁 , 则表示当前线程还不能继续执行 , 因此会自旋等待;反之 , 如果前序线程已经释放锁 , 则当前线程可以继续执行 。
释放锁时 , 也遵循这个逻辑 , 线程会将自身节点的locked位置标记为false , 后续等待的线程就能继续执行了 , 也就是已经释放了锁 。
StampedLock的实现思想总体来说 , 还是比较简单的 , 这里就不展开讲了 。
StampedLock的注意事项在读多写少的高并发环境下 , StampedLock的性能确实不错 , 但是它不能够完全取代ReadWriteLock 。在使用的时候 , 也需要特别注意以下几个方面 。
StampedLock不支持重入
没错 , StampedLock是不支持重入的 , 也就是说 , 在使用StampedLock时 , 不能嵌套使用 , 这点在使用时要特别注意 。
StampedLock不支持条件变量
第二个需要注意的是就是StampedLock不支持条件变量 , 无论是读锁还是写锁 , 都不支持条件变量 。
StampedLock使用不当会导致CPU飙升
这点也是最重要的一点 , 在使用时需要特别注意:如果某个线程阻塞在StampedLock的readLock()或者writeLock()方法上时 , 此时调用阻塞线程的interrupt()方法中断线程 , 会导致CPU飙升到100% 。例如 , 下面的代码所示 。
public void testStampedLock() throws Exception{final StampedLock lock = new StampedLock();Thread thread01 = new Thread(()->{// 获取写锁lock.writeLock();// 永远阻塞在此处 , 不释放写锁LockSupport.park();});thread01.start();// 保证thread01获取写锁Thread.sleep(100);Thread thread02 = new Thread(()->//阻塞在悲观读锁lock.readLock());thread02.start();// 保证T2阻塞在读锁Thread.sleep(100);//中断线程thread02//会导致线程thread02所在CPU飙升thread02.interrupt();thread02.join();}
运行上面的程序 , 会导致thread02线程所在的CPU飙升到100% 。
这里 , 有很多小伙伴不太明白为啥LockSupport.park();会导致thread01会永远阻塞 。这里 , 冰河为你画了一张线程的生命周期图 , 如下所示 。
文章插图
这下明白了吧?在线程的生命周期中 , 有几个重要的状态需要说明一下 。
- NEW:初始状态 , 线程被构建 , 但是还没有调用start()方法 。
- RUNNABLE:可运行状态 , 可运行状态可以包括:运行中状态和就绪状态 。
- BLOCKED:阻塞状态 , 处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized 。
- WAITING:表示等待状态 , 处于该状态的线程需要等待其他线程对其进行通知或中断等操作 , 进而进入下一个状态 。
- TIME_WAITING:超时等待状态 。可以在一定的时间自行返回 。
- TERMINATED:终止状态 , 当前线程执行完毕 。
推荐阅读
- 长的胖的女明星有哪些,女明星胖的有谁-
- 口腔内溃烂
- 林雨申|《飞狐外传》林雨申太帅了,风头盖过男主,但也有一个明显的槽点
- 李世民有几任皇后,李世民登基后的第一个皇后是谁-
- 成都|成都十年艰难故事:我的一个外企同学
- 刘晓庆|刘晓庆和妹妹家中聚会,同穿红色韵味大不同一个美艳一个温婉
- 古羌人特征,古羌人起源地-
- 长衫老人的品质,老人与海老人的品质-
- 泸州特产能带走的
- 西西里的美丽传说|电影《西西里的美丽传说》中的西西里是怎样一个故事?