该类是一个读写锁的改进,它的思想是读写锁中读不仅不阻塞读,同时也不应该阻塞写。

读不阻塞写的实现思路:

在读的时候如果发生了写,则应当重读而不是在读的时候直接阻塞写!

因为在读线程非常多而写线程比较少的情况下,写线程可能发生饥饿现象,也就是因为大量的读线程存在并且读线程都阻塞写线程,

因此写线程可能几乎很少被调度成功!当读执行的时候另一个线程执行了写,则读线程发现数据不一致则执行重读即可。所以读写都存在的情况下,

使用StampedLock就可以实现一种无障碍操作,即读写之间不会阻塞对方,但是写和写之间还是阻塞的!

StampedLock的实现思想

在StampedLock中使用了CLH自旋锁,如果发生了读失败,不立刻把读线程挂起,锁当中维护了一个等待线程队列。

所有申请锁但是没有成功的线程都会记录到这个队列中,每一个节点(一个节点表示一个线程)保存一个标记位(locked),

用于判断当前线程是否已经释放锁。当一个未标记到队列中的线程试图获得锁时,会取得当前等待队列尾部的节点作为其前序节点,

并使用类似如下代码(一个空的死循环)判断前序节点是否已经成功的释放了锁:

while(pred.locked){  }

解释:pred表示当前试图获取锁的线程的前序节点,如果前序节点没有释放锁,则当前线程就执行该空循环并不断判断前序节点的锁释放,

即类似一个自旋锁的效果,避免被系统挂起。当循环一定次数后,前序节点还没有释放锁,则当前线程就被挂起而不再自旋,

因为空的死循环执行太多次比挂起更消耗资源。

读写锁StampedLock的思想的更多相关文章

  1. 源码分析:升级版的读写锁 StampedLock

    简介 StampedLock 是JDK1.8 开始提供的一种锁, 是对之前介绍的读写锁 ReentrantReadWriteLock 的功能增强.StampedLock 有三种模式:Writing(读 ...

  2. Java并发(8)- 读写锁中的性能之王:StampedLock

    在上一篇<你真的懂ReentrantReadWriteLock吗?>中我给大家留了一个引子,一个更高效同时可以避免写饥饿的读写锁---StampedLock.StampedLock实现了不 ...

  3. 正确使用Java读写锁

    JDK8中引入了高性能的读写锁StampedLock,它的核心思想在于,在读的时候如果发生了写,应该通过重试的方式来获取新的值,而不应该阻塞写操作.这种模式也就是典型的无锁编程思想,和CAS自旋的思想 ...

  4. Java8 读写锁的改进:StampedLock(笔记)

         StampedLock是Java8引入的一种新的所机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读 ...

  5. 【漫画】读写锁ReadWriteLock还是不够快?再试试StampedLock!

    本文来源于公众号[胖滚猪学编程] 转载请注明出处! 在互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock一文中,我们对比了互斥锁ReentrantLock和读写锁ReadWr ...

  6. [JDK8]读写锁的改进:StampedLock

    StampedLock是Java8引入的一种新的锁机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读锁会完全阻 ...

  7. 【Java并发工具类】StampedLock:比读写锁更快的锁

    前言 ReadWriteLock适用于读多写少的场景,允许多个线程同时读取共享变量.但在读多写少的场景中,还有更快的技术方案.在Java 1.8中, 提供了StampedLock锁,它的性能就比读写锁 ...

  8. java并发编程-StampedLock高性能读写锁

    目录 一.读写锁 二.悲观读锁 三.乐观读 欢迎关注我的博客,更多精品知识合集 一.读写锁 在我的<java并发编程>上一篇文章中为大家介绍了<ReentrantLock读写锁> ...

  9. Linux多线程实践(6) --Posix读写锁解决读者写者问题

    Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *rest ...

随机推荐

  1. 常用的PHP函数封装,有排序和数据库操作函数

    //二分查找 function bin_sch($array, $low, $high, $k) { if ($low <= $high) { $mid = intval(($low + $hi ...

  2. Java Script 基本知识点

                          JavaScript是一种基于对象和事件驱动的脚本语言,它提供了一些专有的类.对象及函数 1.基本数据类型 JavaScript提供了4种基本的数据类型用来 ...

  3. uoj #450[集训队作业2018]复读机

    传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...

  4. Python爬虫之定时抢购淘宝商品

    Python爬虫之定时抢购淘宝商品 import time from selenium import webdriver import datetime class Spider: def __ini ...

  5. [转载]排序:长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他数的swap

    长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他数的swap 请设计并实现排序. google笔试小题.题目来源:http://wenku.baidu.com/view/5aa818dda5 ...

  6. java冒泡排序小实例

    首先我们了解下什么是冒泡排序: 冒泡排序就是把小的元素往前调或者把大的元素往后调.比较是相邻的两个元素比较,交换也发生在这两个元素之间.所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的: ...

  7. 【ESXI6.0】 ESXI6.0安装时无法安装网卡驱动的解决方法及将网卡驱动加载进ISO

    http://blog.163.com/xifanliang@yeah/blog/static/115078488201571584321787/ 若安装时提示如下图所示 之后安装无法完成,会提示没有 ...

  8. [转]实际项目中如何使用Git做分支管理 (A successful Git branching model)

    来自 https://nvie.com/posts/a-successful-git-branching-model/ In this post I present the development m ...

  9. super、this关键字

    super调用(父类) 调用方法   语法: super.父类方法名(形参列表);        可以在子类方法和构造器中使用,调用父类被覆盖的方法. 实例变量 语法: super.父类实例变量名;  ...

  10. robots.txt防止向黑客泄露网站的后台和隐私

    为了不让搜索引擎索引网站的后台页面或其它隐私页面,我们将这些路径在robots.txt文件中禁用了.但矛盾的是,robots.txt文件任何人都可以访问,包括黑客.为了禁止搜索引擎,我们把隐私泄露给了 ...