热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java并发AQS下的ReentrantReadWriteLock和StampedLock

ReentrantReadWriteLock是ReadWriteLock接口的实现类。ReadWriteLock接口的核心方法是readLock(),writeLoc
ReentrantReadWriteLock

    是ReadWriteLock接口的实现类。ReadWriteLock接口的核心方法是readLock(),writeLock()。实现了并发读、互斥写。但读锁会阻塞写锁,是悲观锁的策略。


JDK1.8下,如图ReentrantReadWriteLock有5个静态方法:
Sync:继承于经典的AbstractQueuedSynchronizer(传说中的AQS),是一个抽象类,包含2个抽象方法readerShouldBlock();writerShouldBlock()
FairSync和NonfairSync:继承于Sync,分别实现了公平/非公平锁。

    如果读取执行情况很多,写入很少的情况下,使用 ReentrantReadWriteLock 可能会使写入线程遭遇饥饿(Starvation)问题,也就是写入线程吃吃无法竞争到锁定而一直处于等待状态。

应用伪代码:

package concurrency.example.lock;import concurrency.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/**Created by William on 2018/4/26 0026*ReentrantReadWriteLock,悲观读,有写就不给读*/
@Slf4j
@ThreadSafe
public class ReentrantReadWriteExample1 {private final Map map &#61; new TreeMap<>();private final ReentrantReadWriteLock lock &#61; new ReentrantReadWriteLock();private final Lock readLock &#61; lock.readLock();private final Lock writeLock &#61; lock.writeLock();private final static Lock reentrantLock &#61; new ReentrantLock();public Data get(String key){readLock.lock();try {return map.get(key);}finally {readLock.unlock();}}public Set getAllKeys(){readLock.lock();try {return map.keySet();}finally {readLock.unlock();}}public Data put(String key, Data value){writeLock.lock();try {return map.put(key,value);}finally {writeLock.unlock();}}class Data{}
}

StampedLock

    StampedLock控制锁有三种模式&#xff08;写&#xff0c;读&#xff0c;乐观读&#xff09;&#xff0c;一个StampedLock状态是由版本和模式两个部分组成&#xff0c;锁获取方法返回一个数字作为票据stamp&#xff0c;它用相应的锁状态表示并控制访问&#xff0c;数字0表示没有写锁被授权访问。在读锁上分为悲观锁和乐观锁。

    所谓的乐观读模式&#xff0c;也就是若读的操作很多&#xff0c;写的操作很少的情况下&#xff0c;你可以乐观地认为&#xff0c;写入与读取同时发生几率很少&#xff0c;因此不悲观地使用完全的读取锁定&#xff0c;程序可以查看读取资料之后&#xff0c;是否遭到写入执行的变更&#xff0c;再采取后续的措施&#xff08;重新读取变更信息&#xff0c;或者抛出异常&#xff09; &#xff0c;这一个小小改进&#xff0c;可大幅度提高程序的吞吐量&#xff01;&#xff01;

应用代码&#xff1a;

package concurrency.example.lock;import java.util.concurrent.locks.StampedLock;/*** 乐观读锁&#xff0c;读操作大量&#xff0c;写操作少的时候&#xff0c;可以使用该锁* 源码例子*/
public class StampedLockExample1 {class Point {private double x, y;private final StampedLock sl &#61; new StampedLock();void move(double deltaX, double deltaY) { // an exclusively locked methodlong stamp &#61; sl.writeLock();try {x &#43;&#61; deltaX;y &#43;&#61; deltaY;} finally {sl.unlockWrite(stamp);}}//下面看看乐观读锁案例double distanceFromOrigin() { // A read-only methodlong stamp &#61; sl.tryOptimisticRead(); //获得一个乐观读锁double currentX &#61; x, currentY &#61; y; //将两个字段读入本地局部变量if (!sl.validate(stamp)) { //检查发出乐观读锁后同时是否有其他写锁发生&#xff1f;stamp &#61; sl.readLock(); //如果没有&#xff0c;我们再次获得一个读悲观锁try {currentX &#61; x; // 将两个字段读入本地局部变量currentY &#61; y; // 将两个字段读入本地局部变量} finally {sl.unlockRead(stamp);}}return Math.sqrt(currentX * currentX &#43; currentY * currentY);}//下面是悲观读锁案例void moveIfAtOrigin(double newX, double newY) { // upgrade// Could instead start with optimistic, not read modelong stamp &#61; sl.readLock();try {while (x &#61;&#61; 0.0 && y &#61;&#61; 0.0) { //循环&#xff0c;检查当前状态是否符合long ws &#61; sl.tryConvertToWriteLock(stamp); //将读锁转为写锁if (ws !&#61; 0L) { //这是确认转为写锁是否成功stamp &#61; ws; //如果成功 替换票据x &#61; newX; //进行状态改变y &#61; newY; //进行状态改变break;} else { //如果不能成功转换为写锁sl.unlockRead(stamp); //我们显式释放读锁stamp &#61; sl.writeLock(); //显式直接进行写锁 然后再通过循环再试}}} finally {sl.unlock(stamp); //释放读锁或写锁}}}
}

总结

1.当只有少量的锁时候&#xff0c;syncronized是很好的实现&#xff0c;不会死锁&#xff1b;
2.竞争者不少&#xff0c;锁数量的增长我们是可以预估的&#xff0c;ReenTrantLock是很好的实现&#xff1b;




推荐阅读
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
  • Python多线程编程技巧与实战应用详解 ... [详细]
  • 在本文中,我们将探讨如何在Docker环境中高效地管理和利用数据库。首先,需要安装Docker Desktop以确保本地环境准备就绪。接下来,可以从Docker Hub中选择合适的数据库镜像,并通过简单的命令将其拉取到本地。此外,我们还将介绍如何配置和优化这些数据库容器,以实现最佳性能和安全性。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
    开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
  • 在深入掌握Spring框架的事务管理之前,了解其背后的数据库事务基础至关重要。Spring的事务管理功能虽然强大且灵活,但其核心依赖于数据库自身的事务处理机制。因此,熟悉数据库事务的基本概念和特性是必不可少的。这包括事务的ACID属性、隔离级别以及常见的事务管理策略等。通过这些基础知识的学习,可以更好地理解和应用Spring中的事务管理配置。 ... [详细]
  • 深入浅析JVM垃圾回收机制与收集器概述
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。 ... [详细]
author-avatar
UTOB
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有