Java并发--使用AQS自定义同步组件TwinsLock

Jdk源码——AQS同步队列解析 前言 本文主要参考自《Java 并发编程的艺术》第五章内容,结合源码对书中内容进行分析补充。 I. Lock接口 在 Lock 接口出现之前,Java程序是靠 synchronized 关键字实现锁功能的,而 Java SE 5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,它提供了与 synchronized 关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。... 阅读详情

TwinsLock

设计一个同步工具:该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程的
访问将被阻塞,我们将这个同步工具命名为TwinsLock。

首先,确定访问模式。TwinsLock能够在同一时刻支持多个线程的访问,这显然是共享式访问,因此,需要使用同步器提供的acquireShared(int args)方法等和Shared相关的方法,这就要求TwinsLock必须重写tryAcquireShared(int args)方法和tryReleaseShared(int args)方法,这样才能保证同步器的共享式同步状态的获取与释放方法得以执行。

其次,定义资源数。TwinsLock在同一时刻允许至多两个线程的同时访问,表明同步资源数为2,这样可以设置初始状态status为2,当一个线程进行获取,status减1,该线程释放,则status加1,状态的合法范围为0、1和2,其中0表示当前已经有两个线程获取了同步资源,此时再有其他线程对同步状态进行获取,该线程只能被阻塞。在同步状态变更时,需要使用compareAndSet(int expect,int update)方法做原子性保障。

最后,组合自定义同步器。前面的章节提到,自定义同步组件通过组合自定义同步器来完成同步功能,一般情况下自定义同步器会被定义为自定义同步组件的内部类。

package pers.zhang.part5;

import com.sun.corba.se.impl.orbutil.concurrent.Sync;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Lock;

/**
 * @author zhang
 * @date 2020/1/20 - 18:35
 * 
 */
public class TwinsLock implements Lock {
    private final Sync sync = new Sync(2);
    
    private static final class Sync extends AbstractQueuedSynchronizer{
        Sync(int count) {
            if(count <= 0){
                throw new IllegalArgumentException("count must large than zero.")
            }
            setState(count);
        }
        

        @Override
        protected int tryAcquireShared(int reduceCount) {
            for(;;){
                int current = getState();
                int newCount = current - reduceCount;
                if(newCount < 0 || compareAndSetState(current, newCount)){
                    return newCount;
                }
            }
        }

        @Override
        protected boolean tryReleaseShared(int returnCount) {
            for(;;){
                int current = getState();
                int newCount = current + returnCount;
                if(compareAndSetState(current, newCount)){
                    return true;
                }
            }
        }
        
    }
    
    @Override
    public void lock(){
        sync.acquireShared(1);
    }
    
    @Override
    public void unlock(){
        sync.releaseShared(1);
    }
    
    //其他接口方法略
}

在上述示例中,TwinsLock实现了Lock接口,提供了面向使用者的接口,使用者调用lock()方法获取锁,随后调用unlock()方法释放锁,而同一时刻只能有两个线程同时获取到锁。

TwinsLock同时包含了一个自定义同步器Sync,而该同步器面向线程访问和同步状态控制。以共享式获取同步状态为例:同步器会先计算出获取后的同步状态,然后通过CAS确保状态的正确设置,当tryAcquireShared(int reduceCount)方法返回值大于等于0时,当前线程才获取同步状态,对于上层的TwinsLock而言,则表示当前线程获得了锁。

测试:

在测试用例中,定义了工作者线程Worker,该线程在执行过程中获取锁,当获取锁之后使当前线程睡眠1秒(并不释放锁),随后打印当前线程名称,最后再次睡眠1秒并释放锁。

package pers.zhang.part5;

import org.junit.Test;
import pers.zhang.part4.SleepUtils;

import java.util.concurrent.locks.Lock;

/**
 * @author zhang
 * @date 2020/1/20 - 18:42
 */
public class TwinsLockTest {

    @Test
    public void test(){
        final Lock lock = new TwinsLock();
        class Worker extends Thread{
            @Override
            public void run(){
                while(true){
                    lock.lock();
                    try{
                        SleepUtils.second(1);
                        System.out.println(Thread.currentThread().getName());
                        SleepUtils.second(1);
                    }finally {
                        lock.unlock();
                    }
                }
            }
        }

        //启动10个线程
        for(int i = 0; i < 10; i++){
            Worker w = new Worker();
            w.setDaemon(true);
            w.start();
        }

        //每隔1秒换行
        for(int i = 0; i < 10; i++){
            SleepUtils.second(1);
            System.out.println();
        }
    }
}

运行该测试用例,可以看到线程名称成对输出,也就是在同一时刻只有两个线程能够获取到锁,这表明TwinsLock可以按照预期正确工作。

基于Android Studio的校园智能点餐系统开发实战(附完整源码与部署指南) 本文详细介绍了基于Android Studio开发校园智能点餐系统的完整流程,包括需求分析、环境搭建、数据库设计、客户端与后台功能实现。系统采用SSM框架和MySQL数据库,解决了校园食堂高峰期排队问题,提供高效的点餐体验。附完整源码与部署指南,助力开发者快速构建类似应用。 阅读详情

相关推荐

别再为跨页读写发愁了!STM32F407模拟I2C驱动24C256/512的避坑指南

本文详细解析了STM32F407模拟I2C驱动24C256/512的跨页写入问题,揭示了24C系列存储器'写满一页不会自动翻页'的关键机制,并提供了经过验证的分页写入算法和优化方案。通过GPIO时序优化、地址计算和错误处理等技巧,帮助开发者解决数据错乱、覆盖等常见问题,实现稳定可靠的EEPROM读写操作。

weixin_42631411的博客 377

TwinsLock——自定义同步组件

TwinsLock——自定义同步组件设计目的设计方案代码实现 参考书籍:《Java并发编程的艺术》 设计目的   设计一个同步工具,该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程访问将被阻塞,将这个同步工具命名为TwinsLock。 设计方案   首先,确定访问模式。分为独占式访问和共享式访问,由于TwinsLock需要同一时刻至多两个线程能访问,因此属于共享式访问。因此需要使用同步器提供的acquireShared(int args)方法和Shared相关的方法,这就要求重写AQS的tryAc

qq_41523340的博客 413

学生党投稿Applied Soft Computing:从导师账号登录到通讯作者设置的全流程解惑

本文详细解析了学生投稿Applied Soft Computing期刊的全流程,重点介绍了导师账号登录、通讯作者设置、作者排序调整以及开放获取费用等关键环节的避坑技巧。针对LaTeX稿件处理和财务选项选择提供了实用建议,帮助学生顺利完成SCI期刊投稿。

weixin_30352191的博客 211

AQS实战-自定义同步组件TwinsLock

TwinsLock在同一时刻允许至多两个线程的同时访问,表明同步资源数为2,这样可以设置初始状态status为2,当一个线程进行获取,status减1,该线程释放,则status加1,状态的合法范围为0、1和2,其中0表示当前已经有两个线程获取了同步资源,此时再有其他线程对同步状态进行获取,该线程只能被阻塞。在同步状态变更时,需要使用compareAndSet(int expect,int update)方法做原子性保障。自定义同步组件通过组合自定义同步器来完成同步功能,...

贾欣晓的博客 400

osgearth2.10 demo功能介绍

osgearth-2.10 demo: 说明: 1、运行环境win7 x64 旗舰版,CPU i5-6400 8核,8G内存; 2、括号内是对应demo的测试参数(.earth); 3、配置OSG_FILE_PATH; 4、参数命令行可以查看各个demo需要的输入参数; 5、前缀说明:gui界面程序、cmd控制台程序、non功能未知; 6、程序后括号里的non表示不需要通过命令行输入参数; 示例: 1、gui:osgearth_3pv(simple.earth):相机与地球的投影关系,Range表示相机

rach09的专栏 2422

【系统分析师】2026年上半年真题:论文及解题思路

四篇论文围绕系统与开发实践展开: 安全架构设计强调数据加密(国密算法)、零信任访问控制及容灾架构,以某医疗云平台为例,实现RTO<5分钟的高可用保障。 架构风格应用解析微服务/事件驱动等风格选型,结合电商平台案例,通过服务拆分与异步通信提升扩展性。 需求评审机制提出正式评审与走查结合的方法,在金融系统中减少30%返工,解决业务规则二义性问题。 LLM测试生成利用大模型从需求/代码生成用例,辅以人工校验,使测试效率提升50%,覆盖边缘场景。 各篇均遵循“背景-理论-实践”结构,突出

数据知道的博客 784

java 共享锁_[Java源码][并发J.U.C]---用代码一步步实现AQS(3)---共享锁的获取和释放...

例子1: 共享锁的获取和释放与前面两篇文章不一样的是本文将以一个例子开头先看看共享锁是怎么样一回事.如下所示, TwinsLock 是一个共享锁, 可以最多允许两个线程获得锁,importjava.util.concurrent.TimeUnit;importjava.util.concurrent.locks.Condition;publicclassTwinsLockimplemen...

weixin_31067983的博客 227

seurat v5更新及样本整合方法

1 Seurat 对象和 Assay 类发生了变化:支持更多种类的检测和数据类型,包括磁盘上的矩阵。引入了分层结构来存储数据,例如原始计数、标准化数据和 z 得分/方差稳定数据。可以使用 $ 访问器或 LayerData 函数来访问数据。现有的 Seurat v4 函数和工作流程仍可在 v5 中使用。2 整合工作流程发生了变化:简化了整合流程,提高了速度和内存效率。整合结果与 v4 工作流程略有不同,但用户仍可在 v5 中运行 v4 整合工作流程。

hx2024的博客 2686

Lock接口与队列同步器

Lock接口 锁是用来控制多个线程访问共享资源的方式。在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能,在Java SE5之后,并发包新增了Lock接口以及相关实现类用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显示地获取和释放锁。 使用synchronized关键字会隐式地获取锁,但它将锁的获取和释放固化了。 Lock的使用方式: Lock lock = new ReentrantLock(); lock.lock(); try {

... 226

矿石生成(1)

这个提供了标准化的矿石放置配置模板简化了常见和稀有矿石的配置过程遵循了Minecraft原版的世界生成模式提高了代码的可读性和可维护性通过使用这个类,模组开发者可以更轻松地配置矿石的生成规则,而不需要每次都手动编写完整的放置修饰符列表。这种设计模式在原版Minecraft和其他大型模组中也很常见,是一种良好的编程实践。// 导入语句...// 字段和方法...包声明表明这个类位于luckymod模组的WorldGen包中,专门处理世界生成相关配置。导入语句。

qq_24992377的博客 137

Ros入门 (十)----激光雷达避障 简易实现

本篇文章通过订阅/scan话题获取障碍物的距离信息,达到避障目的,提供部分代码,仅供参考。

weixin_51157015的博客 1万+

自定义同步组件——TwinsLock

设计一个同步工具,该工具同一个时刻,只允许两个线程同时访问,超过两个线程访问将会被阻塞。 分析:首先,确定访问模式,TwinLock能够同一时刻支持多个线程同时访问,这明显是共享式访问。这需要同步器提供的acquireShared(int args)方法和Share相关的方法,同时要求重写tryAcquireShared(int args)等方法。 其次,定义资源数量,TwinsLock在同一...

jcsyl_mshot的博客 674

TC3XX - MCAL知识点(九):PWM EB-tresos配置说明及代码浅析

脉冲宽度调制(PWM)驱动器负责提供与AUTOSAR指定的PWM信号生成相关的标准服务。PWM通道的底层定时器驱动是GTM (TOM或ATOM片)或CCU6 (T12或T13片)定时器通道。软硬件匹配关系如下:PWM直接引用的是GTM与CCU6模块,然后GTM与CCU6再关联到Port的,根据软硬件匹配关系,也能调用中断来使用,本例子没使用中断。CCU6是一个高分辨率的16位捕获和比较单元,具有特定的应用模式,主要用于交流驱动控制。特殊的工作模式支持控制无刷直流电机使用霍尔传感器或反电动势检测。

梦想技术家 2887

Java并发编程-锁(六)

AQS用法:自定义独占锁和共享锁

gdr12的专栏 726

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

读书笔记-Java并发编程的艺术-第5章(Java中的锁)-第1节(Lock接口)、第2节(队列同步器)

Java并发编程的艺术 Java中的锁 Lock接口 队列同步器

心流时间的博客 1070

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

并发-Java中的锁---Lock接口、队列同步器AQS笔记

确定访问模式:能同一时刻支持多个线程访问是共享式访问,需要使用同步器提供的acquireShared方法和shared相关的方法,TwinsLock要重写tryAcquireShared和tryReleaseShared方法,这样保证同步器共享式同步状态的获取与释放方法得以执行。定义资源数:同一时刻允许最多两个线程同时访问,表明同步资源数为2,这样设置初始状态status为2,当线程获取,status减1,线程释放,加1,状态合法范围0(表示当前已经有两个线程获取了同步资源,再有其他获取,阻塞),1,2。

weixin_39795049的博客 361

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深入理解并发编程-AQS(队列同步器)

本文为读书笔记,书籍为Javab并发编程的艺术 1. Lock接口 在finally块中释放锁,目的是保证在获取到锁之后,最终能够被释放。 不要将获取锁的过程写在try块中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放。 与synchronized相比: 2. AbstractQueuedSynchronizer(AQS) AQS主要使用方式是继承...

littlewhitevg的博客 400

JUC 自定义至多有2个线程获取同步状态的同步组件TwinsLock

自定义同步组件 TwinsLock TwinsLock.java 自定义简单的同步组件,该工具至多只允许2个线程同时访问,超过2个线程的访问将被阻塞,加入到同步队列中,这个自定义规则的工具为TwinsLock。 由于允许2个线程同时获取同步锁,所以该同步组件是共享的。 通俗的说:AQS是写同步的规则,而Lock接口是AQS的代理者,用Lock接口的实现方法去调用AQS的方法实现同步。AQS面向写...

阿星小天地 381

Java并发:AbstractQueuedSynchronizer(AQS)

队列同步器 AbstractQueuedSynchronizer 是一个公共抽象类。提供一个同步器框架,用于实现依赖于先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量,事件等)。使用一个 int 成员变量表示同步状态,通过内置的 FIFO 队列来完成资源获取线程的排队工作。 同步器的使用主要是通过集成这个抽象类并实现它的抽象方法来管理同步状态,这个抽象提供了三个方法来对同步状态...

weixin_30275415的博客 135

Java中的锁--Java并发编程的艺术读书笔记

Java中的锁1 Lock接口2 队列同步器AQS2.1 AQS的接口与示例2.2 AQS的实现分析2.2.1 同步队列2.2.2 独占式同步状态获取与释放2.2.3 共享式同步状态获取与释放2.2.4 独占式超时获取同步状态2.2.5 自定义同步组件——TwinsLock3 重入锁3.1 实现重进入3.2 公平与非公平获取锁的区别4 读写锁4.1 读写锁的接口与示例4.2 读写锁的实现分析4.2.1 读写状态的设计4.2.2 写锁的获取与释放4.2.3 读锁的获取与释放4.2.4 锁降级5 LockSup

qq_41523340的博客 698

队列同步器AbstractQueuedSynchronizer(AQS)

同步器的设计是基于模板方法模式的,即使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法会调用使用者重写的方法 先看下类的定义: public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer imple...

Autumn匆的博客 398

011-多线程-基础-基于AbstractQueuedSynchronizer自定义同步组件

一、概述   队列同步器AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架。 1.1、自定义独占锁同步组件   设计一个同步工具:该工具在同一时刻,只允许一个线程访问,超过一个线程的访问将被阻塞,我们将这个同步器命名为Mutex。   首先,确定访问模式,MutexLock在同一时刻只支持一个线程的访问,这显然是独占式访问,因此,需要使用...

dilv4062的博客 115

Java并发编程(自定义同步组件)

并发包结构图: 编写一个自定义同步组件来加深对同步器的理解业务要求: * 编写一个自定义同步组件来加深对同步器的理解。 * 设计一个同步工具:该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程的 * 访问将被阻塞,我们将这个同步工具命名为TwinsLock。 * 首先,确定访问模式。TwinsLock能够在同一时刻支持多个线程的访问,这显然是共享式 * 访问,因此,需要

Achiberx 568

Java并发编程之自定义同步组件

队列同步器AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架,我们前面已经对该类进行了实现层面的分析,下面我们编写两个自定义同步组件来加深对AQS的理解。自定义独占锁同步组件设计一个同步工具:该工具在同一时刻,只允许一个线程访问,超过一个线程的访问将被阻塞,我们将这个同步器命名为Mutex。首先,确定访问模式,Mutex在同一时刻只支持一个线程的访问,这显...

Stay Hungry, Stay Foolish 463

JUC包(三) 锁与锁实现(AQS)

前言 在原 JUC包 (一) 原子类 与 CAS操作中我们主要了解了什么是原子操作,以及原子操作的实现CAS(Compare ans Swap)操作. 本章,我们继续接着介绍使用CAS原理实现的锁操作. 锁在JUC包中使用非常广泛, 其取代了传统的synchronized关键字被广泛使用. 下文中,我们将一起了解锁的实现原理与基本使用场景. 队列同步器(AQS) AQS,是(Abstract ...

Be yourself. 754

【隐匿撕源码】从ReentrantLock剖析AQS

前言 鼠年新的工作日开始了,新的一年新的工作学习,第一个工作日给自己定一些要求吧。 想写一个系列【隐匿撕源码】 剖析各种经典框架,工具,JDK的源码提升自己,同时给大家分享一些心得。这篇文章就作为开端,干就完事了。 从ReentrantLock开始 ReentrantLock 是JDK给我们提供的显示锁 在功能上远远强于synchronized 是功能上 不是性能上,随着JDK版本的一代又一代升级...

qq_43091847的博客 546
上一篇: Java并发--队列同步器(AQS)的实现分析
下一篇: Java并发--重入锁(ReentrantLock)
吴声子夜歌
博客等级 码龄9年 2688粉丝 2268原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值