【并发编程】AQS——详细解释公平锁,非公平锁,独占锁,什么是可重入以及condition

目录

1、公平

2.非公平

3.独占锁

4.可重入

5.condition


1、公平


第一步:获取状态的 state 的值。如果 state=0 即代表锁没有被其它线程占用,执行第二步。如果 state!=0 则代表锁正在被其它线程占用,执行第三步。
第二步:判断队列中是否有线程在排队等待。如果不存在则直接将锁的所有者设置成当前线程,且更新状态 state 。如果存在就入队。
第三步:判断锁的所有者是不是当前线程。如果是则更新状态 state 的值。如果不是,线程进入队列排队等待。


2.非公平


第一步:获取状态的 state 的值。如果 state=0 即代表锁没有被其它线程占用,则设置当前锁的持有者为当前线程,该操作用 CAS 完成。如果不为0或者设置失败,代表锁被占用进行下一步。
此时获取 state 的值,如果是0,代表刚好线程释放了锁,此时将锁的持有者设为自己如果不是0,则查看线程持有者是不是自己如果是,则给state+1,获取锁如果不是,则进入队列等待


3.独占锁


AQS 在锁的获取时,并不一定只有一个线程才能持有这个锁,所以此时有了 独占模式和共享模式 的区别,我们本篇文章中的 ReentrantLock 使用的就是独占模式,在多线程的情况下只会有一个线程获取锁。

4.可重入


可重入锁就是当前持有锁的线程能够多次获取该锁,无需等待

AQS实现一个可重入锁

 package com;
 
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
 
public class MyLock implements Lock {
    private Helper helper = new Helper();
 
    private class Helper extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            // 第一个线程进来,可以获取锁
            // 第二个线程进来,无法获取锁,返回false
            Thread thread = Thread.currentThread();
            // 判断是否为第一个线程进来
            int state = getState();
            if (state == 0) {
                if (compareAndSetState(0, arg)) {// 如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值
                    // 设置当前线程
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
            } else if(getExclusiveOwnerThread() == thread) { // 允许重入锁,当前线程和当前保存的线程是同一个线程
                setState(state + 1);
                return true;
            }
            return false;
        }
 
        /***
         * 释放锁
              此方法总是由正在执行释放的线程调用。
         */
        @Override
        protected boolean tryRelease(int arg) {
            // 锁的获取和释放肯定是一一对应的,那么调用此方法的线程一定是当前线程
            if (Thread.currentThread() != getExclusiveOwnerThread()) {
                throw new RuntimeException();
            }
            
            boolean flag = false;
            int state = getState() -arg;
            if (state == 0) {// 当前锁的状态正确
                setExclusiveOwnerThread(null);
                flag = true;
            }
            setState(state);
            return flag;
        }
 
        protected Condition newCondition() {
            return new ConditionObject();
        }
    }
 
    @Override
    public void lock() {
        // 独占锁
        helper.acquire(1);
    }
 
    @Override
    public void lockInterruptibly() throws InterruptedException {
        // 可中断
        helper.acquireInterruptibly(1);
    }
 
    @Override
    public boolean tryLock() {
        return helper.tryAcquire(1);
    }
 
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return helper.tryAcquireNanos(1, unit.toNanos(time));
    }
 
    @Override
    public void unlock() {
        helper.release(1);
    }
 
    @Override
    public Condition newCondition() {
        return helper.newCondition();
    }
}

5.condition


在Java并发编程中,每个Java堆中的对象在“出生”的时刻都会“伴生”一个监视器对象,而每个Java对象都会有一组监视器方法:wait()、notify()以及notifyAll()。我们可以通过这些方法实现Java多线程之间的协作和通信,也就是等待唤醒机制,如常见的生产者-消费者模型。但是关于Java对象的这组监视器方法我们在使用过程中,是需要配合synchronized关键字才能使用,因为实际上Java对象的等待唤醒机制是基于monitor监视器对象实现的。与synchronized关键字的等待唤醒机制相比,Condition则更为灵活,因为synchronized的notify()只能随机唤醒等待锁的一个线程,而Condition则可以更加细粒度的精准唤醒等待锁的某个线程。与synchronized的等待唤醒机制不同的是,在monitor监视器模型上,一个对象拥有一个同步队列和一个等待队列,而AQS中一个锁对象拥有一个同步队列和多个等待队列。对象监视器Monitor锁实现原理如下:


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ICSpector:一款功能强大的微软开源工业PLC安全取证框架

关于ICSpector ICSpector是一款功能强大的开源工业PLC安全取证框架,该工具由微软的研究人员负责开发和维护,可以帮助广大研究人员轻松分析工业PLC元数据和项目文件。 ICSpector提供了方便的方式来扫描PLC并识别ICS环境中的可疑痕迹,可以用于…

Spring与Web环境集成

1. Spring与Web环境集成 1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) ,这…

RX4901CE (RTC模块)

RX4901CE是一个集成了32.768 kHz数字温度补偿晶体振荡器(DTCXO)的RTC模块。高稳定性,低电流消耗,时间戳功能,当外部或内部事件发生时,可以记录多达32个日期和时间,以及基本的RTC功能,如时间和日历&#xff…

江科大STM32 中

目录 6、TIM(Timer)定时器基本定时器通用定时器高级定时器示例程序(定时器定时中断&定时器外部时钟)TIM输出比较示例程序(PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱动直流电机)TIM输入捕获示例程序&…

微信小程序登录获取手机号教程(超详细)

1. 背景介绍: 在我们开发微信小程序时,登录时,需要获取用户手机号作为唯一标识,下面我介绍一下获取手机号的教程。 本篇文章介绍后端获取方法: 前端工作 后端工作 前端 新建Page页面,在xxx.wxml中加入…

Linux的 .bashrc 有什么作用?

一、.bashrc 是什么? 有什么用? .bashrc是一个存储在你的home目录下的隐藏文件,它用来配置和自定义你的终端环境和行为。 每次你启动一个新的终端时,.bashrc文件就会被执行,加载你设置的环境变量,别名,函数…

Linux下的gcc与g++

文章目录 一.Linux gcc与g1.gcc如何生成可执行程序(g同)2.函数库 二.Linux项目自动化构建工具-make/makefile 一.Linux gcc与g 1.gcc如何生成可执行程序(g同) 预处理(宏定义替换,展开头文件代码,条件编译,去注释&…

京东云开发者DDD妙文欣赏(3-4)什么时候厨师是Actor

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 京东云开发者DDD妙文欣赏(1-2)报菜名和化繁为简的创新>> 图8 《餐厅》中的“用例图” (01) 原文 用例图 赏析 揉一揉眼睛仔细…

目标检测 - RCNN系列模型

文章目录 1. RCNN2. Fast-RCNN3. Faster-RCNN 1. RCNN 论文:Rich feature hierarchies for accurate object detection and semantic segmentation 地址:https://arxiv.org/abs/1311.2524 分为两个阶段: 目标候选框Object ProposalsProposal…

04 SB实战 -微头条之头条模块(登录验证拦截器+发布文章+修改文章)

1.登陆验证 为什么还要做登陆验证? 尽管先前我们已经进行过登录, 但是要知道token是有有效期的, 而用户登陆后有可能长时间停留在页面不退出, 甚至这个停留的时间超出token有效期, 因此,尽管用户已经登录, 但是, 在需要登录才能进行的操作(进入发布页前、发布新闻前、进入修改…

MongoDB单机部署

Windows系统安装启动 下载安装包 附件中已准备好win32位、win64位安装包 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址:https://www.mongodb.com/download-cente…

MATLAB curve fitting toolbox没有怎么办?

版本:MATLAB R2023b 如果在安装MATLAB时仅仅选择了安装MATLAB,而并未选择其他选项,则在进入MATLAB后会发现顶部的APP栏中无法找到曲线拟合工具箱。 本人跟随MATLAB中的教程进行下载时,出现了如下报错: 最终解决方案&a…

【机器学习300问】19、深度学习和机器学习什么关系?

之前的文章都聚焦在传统的机器学习上,作为入门,学了许多机器学习的基础。往后的文章我会穿插着机器学习和深度学习的内容进行,所有有必要在这里先说下两者的关系。 一、从范围上讲 深度学习和机器学习都是人工智能的一个子领域,它…

自然语言NLP学习

2-7 门控循环单元(GRU)_哔哩哔哩_bilibili GRU LSTM 双向RNN CNN 卷积神经网络 输入层 转化为向量表示 dropout ppl 标量 在物理学和数学中,标量(Scalar)是一个只有大小、没有方向的量。它只用一个数值就可以完全…

Elasticsearch内核解析 - 数据模型篇

Elasticsearch内核解析 - 数据模型篇 - 知乎 Elasticsearch是一个实时的分布式搜索和分析引擎,它可以帮助我们用很快的速度去处理大规模数据,可以用于全文检索、结构化检索、推荐、分析以及统计聚合等多种场景。 Elasticsearch是一个建立在全文搜索引擎…

对齐大型语言模型与人类偏好:通过表示工程实现

1、写作动机: 强化学习表现出相当复杂度、对超参数的敏感性、在训练过程中的不稳定性,并需要在奖励模型和价值网络中进行额外的训练,导致了较大的计算成本。为了解决RL方法带来的上述挑战,提出了几种计算上轻量级的替代方案&…

虹科分享丨汽车技术的未来:Netropy如何测试和确保汽车以太网的性能

来源:艾特保IT 虹科分享丨汽车技术的未来:Netropy如何测试和确保汽车以太网的性能 原文链接:https://mp.weixin.qq.com/s/G8wihrzqpJJOx5i0o63fkA 欢迎关注虹科,为您提供最新资讯! #汽车以太网 #车载网络 #Netropy …

程序员自由创业周记#25:一个功能的诞生

程序员自由创业周记#25:一个功能的诞生 快捷启动 记录在创业项目 Island Widgets-学伟灵动岛锁屏小组件 中新增一个功能的诞生过程。 功能名称:快捷启动。 人话:不用回到桌面在锁屏界面或者灵动岛就能打开其他App、网页或快捷指令。 使用…

uniapp安卓android离线打包本地打包整理

离线打包准备 下载Android studio 1.准备资源hbuilder 2.准备离线SDK 最新android平台SDK下载最新android平台SDK下载 3.离线打包key申请 4.直接导入HBuilder-Integrate-AS工程,直接运行simpleDemo项目即可 5.安装java 1.8 jdk-8u151-windows-x64 6.遇到这个报错报错Caus…

什么时间平仓?什么时间反转?只需这个信号,WeTrade1秒找到

知道什么时间平仓?什么时间反转?交易还会有亏损的存在吗?那么怎么找到平仓和反转的信号呢?其实很简单,WeTrade1秒找到。 我们可以用以前的交易方法,在突破蜡烛线的高点或低点设置止损单。初始止盈必须至少是止损长度的两倍。我们用的是趋势交易&…