Java lock锁的一些细节

MUSIC算法翻车?Toeplitz矩阵重构如何解决DOA估计中的相干信源难题 本文深入探讨了MUSIC算法在相干信源DOA估计中失效的根本原因,并详细介绍了基于Toeplitz矩阵重构的协方差矩阵修复技术。该方法通过凸优化恢复协方差矩阵的理想结构,有效解决了信号子空间秩亏损问题,从而显著提升了MUSIC算法在相干和多径场景下的分辨精度与稳健性。 阅读详情

前言

lock是Java接口,采用乐观锁的设计思想,采用CAS操作来实现的一个锁,这几点跟synchronized不同,synchronized原始采用的是CPU悲观锁机制。

为什么需要LOCK 锁

1.5之前大家都用synchronized锁,怎么突然要搞一个lock锁?大家都不喜欢重复造轮子,一件事有人干了,你就别重复了,没必要,但Java源码开发者难道不懂这个道理,他们的考虑是什么?我们来看看:

  • 1、获取到锁后,如果获取不到资源,是不是要等待?
    synchronized锁确实是,没有获取到足够的资源,就要一直等待,它是不能释放掉的,你也改不了它,似乎有点别扭

  • 2、超时设置
    synchronized锁 是没有超时设置的,如果一个线程等待超时了,自动释放掉,让其他线程来处理,似乎是一个不错的设计。

于是有人就说了,再来一个锁,于是lock锁出现了。

lock锁怎么获取锁

通过volatile 修饰的state变量来控制,底层通过cas来设置变量,设置成功就获取锁成功。

  • state == 0
    这个状态表示锁被释放了,但不会说这个时刻就是你获取了锁,如果有其他线程在队列里,可能需要互相竞争,获取了锁,就会唤醒线程,没有获取锁的线程被加入到AQS的队列中,自旋方式来获取同步状态state,等待唤醒。
  • state > 0
    表示锁被占用,需要通过类似自旋的方式来获取同步状态,直到这个同步状态等于0。

如果当前线程已经拥有该锁,再调用lock()方法会立即返回。那么就可以执行lock() 与 unlock() 之间的代码逻辑。

公平锁、非公平锁

公平锁主要是根据排队的线程先后顺序来抢占资源,非公平锁就是看每个线程本事,自由竞争锁资源。通过字段来控制公平和非公平,这个有默认值的。

如何保证公平

非公平其实很好实现,大家都自由竞争,公平则是靠AQS 来实现,AQS全程是 Abstract Queued Synchronizer,中文叫做队列同步器,是一个抽象队列安全器,这个AQS主要是面向锁的实现的,用作构建lock的主要组建,所以有些博客里认为:

  • lock锁是面向使用者
  • AQS 是面向锁的,AQS屏蔽里同步状态管理、线程排队、等待\唤醒 等一些底层操作。这句话是我抄的,文字表达很得体。

其实非公平就是每次来一个线程抢锁,抢到就是你的,抢不到,你就老老实实的去排队,不过在tryAcquire方法中也有不用,公平锁会判断当前节点是不是第一个节点,如果不是就继续自旋,非公平就不会有这一步判断

static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))  // 这里 会去cas同步状态,失败了就执行acquire(1); 其实就变成了公平锁。
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);  // 注意这个差异
        }
    }

    /**
     * Sync object for fair locks
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

独占和共享

在实际的实现方式上,有2种方式,独占和共享:

  • 独占式 Exclusive
    只要AQS的state变量不为0,并且持有锁的线程不是当前线程,那么代表资源不可访问,其他线程进来就会获取失败,并且加入到同步队列中。意思就是同步状态state是只能一个线程占有。如ReentrantLock利用了其独占功能。
  • 共享式 Share
    只要AQS的state变量不为0,那么代表资源不可以访问。但共享式在同一时刻可以有多个线程获取同步状态。例如读操作可以多个线程同时读,写操作同一时刻只能有一个线程写。 采取自旋的方式来获取同步状态会竞争资源。CountDownLatch,Semaphore利用了其共享功能。

共享式与独占式的最主要区别在于同一时刻独占式只能有一个线程获取同步状态,而共享式在同一时刻可以有多个线程获取同步状态。

  • 如果某个同步器支持独占的获取操作,那么需要实现一些保护方法,包括tryAcquire、tryRelease、isHeldExclusivery等。
  • 对于支持共享获取的同步器,则应该实现tryAcquireShared、tryReleaseShared等方法。

AQS的acquire、acquireShared、release、releaseShared等方法都将调用这些方法在子类中带有前缀try的版本来判断某个操作。一层一层调用:lock --> acquire --> tryAcquire ,这样三层一层一层调用。

AQS 队列同步器

AQS解决了在实现同步器时涉及的大量细节问题,例如获取同步状态、FIFO同步队列。基于AQS来构建同步器可以带来很多好处:

  • 极大的减少实现工作,而且也不必处理在多个位置上发生的竞争问题。
  • 在基于AQS构建的同步器中,只能在一个时刻发生阻塞,从而降低上下文切换的开销,提高了吞吐量。
  • 同时在设计AQS时充分考虑了可伸缩性。

因此JUC中,所有基于AQS构建的同步器均可以获得这个优势。 AQS的主要使用方式是继承,子类通过继承同步器,并实现它的抽象方法来管理同步状态。AQS使用一个int类型的成员变量state来表示同步状态:

  • 1、当state>0时,表示已经获取了锁。
  • 2、当state=0时,表示释放了锁。

它提供了三个方法,来对同步状态state进行操作,并且AQS可以确保对state的操作时安全的: getState(); setState(int newState); compareAndSetState(int expect, int update); 另外,AQS通过内置的双向FIFO同步队列来完成资源获取线程的排队工作:

  • (1)如果当前线程获取同步状态(锁)失败时,AQS则会将当前线程以及等待状态等信息构造一个节点(Node)并将其加入同步队列,同时会阻塞当前线程。
  • (2)当同步状态(锁)释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。

在这里插入图片描述
一个节点(Node)表示一个线程,它保存着线程的引用(thread)、状态(waitStatus)、前驱节点(prev)、后继节点(next)。入队逻辑实现的addWaiter(Node)方法,需要考虑并发情况。为了解决并发问题,它通过CAS方式,来保证正确的添加Node。

实现阻塞

我们想直接放弃一个线程的时候,可以阻塞、中断这个线程或者stop掉,AQS内部其实是用LockSupport。JDK描述LockSupport为构建锁和其他同步类的基本线程阻塞原语,构建更高级别的同步工具集。LockSupport提供的park/unpark从线程的粒度上进行阻塞和唤醒,park/unpark模型真正解耦了线程之间的同步,线程之间不再需要一个Object或者其它变量来存储状态。

ReentrantLock和Synchronized有什么异同

首先他们肯定具有相同的功能和内存语义。不同之处在于以下几点:

  • 1、与synchronized相比,ReentrantLock提供了更多更加全面的功能,具备更强的扩展性。例如时间锁等候,可中断锁等候和锁投票。
  • 2、ReentrantLock还提供了条件Condition,对线程的等待唤醒操作更加详细灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合。
  • 3、ReentrantLock提供了可轮询的锁请求,它会尝试去获取锁,如果成功则继续,否则等到下次运行时处理,而synchronized则一旦进入锁请求要么成功要么阻塞, 所以相对于synchronized来说,ReentrantLock会不容易死锁些。
  • 4、ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在一个synchronized块结构中获取和释放。
  • 5、ReentrantLock支持中断处理,且性能相对好一些

参考博客

深入Lock锁底层原理实现,手写一个可重入锁
万字超强图文讲解AQS以及ReentrantLock应用
面试-并发编程之AQS及可重入锁

CCSP考后复盘:那些刷题时感觉良好,考场却发懵的题目到底长什么样? 本文深入分析了CCSP考试中常见的题目陷阱和解题策略,揭示了刷题与实战的差距。通过解析换装题、双胞胎选项和场景题等典型题型,帮助考生掌握拆题技巧和思维模式转变,提升应对CCSP考试的能力。 阅读详情

相关推荐

在Unity3d使用yolov8的onnx模型

输出OUTPUTS是float32[1,35,8400],表示它会输出一个大小为[1, 35, 8400]的浮点数张量。这个输出张量的维度表示了检测到的目标的数量、每个目标的预测参数以及网格单元的数量。输出张量的第一个维度1表示检测到的目标数量。每个目标由35个值组成,表示目标的类别、置信度、边界框的坐标及10个特定点的位置。要取得8400个数据中置信度最高的数据,然后获取该数据其他channel的数据。运行结果:(蓝色是检测手的边框,红点是自定义的点),其中的四个数字分别表示不同的维度。

shenqingyu0605202324的博客 5603

Java 操作 word 文档 (三)段落Paragraphs,文本加粗、斜体、字体、字体大小、复杂文本

1、段落标签 在 WordML 中,段落由 <w:p> 标签定义。 每个段落都有属性标签:<w:pPr> 。其中包含一些属性标签,比如段落的对其方式:<w:jc> ;段落的边框:<w:pBdr> 。 一般情况下:段落的内容就是一个或多个 <w:r> 标签构成。 2、引入 docx4j 2.1 引入 docx4j 的 maven 依赖 <dependency> <groupId>org.docx4

llk15884975173的博客 8006

优刻得首个「国产千卡智算集群」落地,支持智源千亿大模型训练

在人工智能引领的时代浪潮中,算力已成为技术进步与创新的核心驱动力。面对当下AI算力需求的飙升、高端AI芯片供应受限的挑战,加之OpenAI带来的技术封锁,唯有坚定不移的发展自主可控的国产技术方案,持续壮大国产智算集群规模,才能一路突破围追堵截,进一步促进国产大模型产业生态繁荣。集群还提供了完善高效的软件栈工具,集成多种主流的深度学习编程框架,通过测试验证,确保了对行业领先人工智能模型的高效支持,做到开箱即用,用户可快速投入模型的开发和部署,加速了其在人工智能领域的布局和发展。方面取得了显著成效。

Ucloud_TShare的博客 1473

JAVA - 使用Apache POI生成word(四)Paragraph篇(在word中写入文字并设置样式)

使用Apache POI 在word中写入文字并设置样式

qq_38670087的博客 5265

UNSW-NB15数据集:网络流量分析与恶意攻击检测实战指南

本文提供了UNSW-NB15数据集在网络流量分析与恶意攻击检测领域的实战指南。详细介绍了该数据集的构成、核心特征解析、特征工程处理、机器学习模型训练与评估方法,并探讨了模型部署及持续优化的挑战与思路,帮助读者构建高效的网络攻击检测系统。

weixin_29193359的博客 258

单细胞 | pySCENIC·转录因子分析(二)

接上一篇,pySCENIC分析完之后就可以进行可视化了,个人认为最重要的有三个图:rss点图,rank图,转录因子表达水平热图,3个图结合着看。3.可视化rank图,可以自己改一下plotRSS_oneSet参数让图更好看一点。4. regulon表达水平热图,转录因子表达水平同理,得到的图类似只是输入不一样。2.可视化点图:寻找cluster特异性转录因子。1.loom文件读入R,提取数据。

生信练习生 4283

java如何设置1.5倍行距_Java如何在iText中设置段落行间距?

要设置的行间距在iText的段落可以通过传递线空间/领先的参数进行Paragraph构造。在下面的示例中,我们将行距设置为32。我们还可以通过调用此对象的setSpacingBefore()和setSpacingAfter()方法来设置段落之间的间隔。packageorg.nhooo.example.itextpdf;importcom.itextpdf.text.Chunk;importc...

weixin_36072221的博客 2528

损失函数大汇总(五十三)(Boundary Loss附公式推导与代码)

摘要 Boundary Loss是一种针对图像分割任务的新型损失函数,特别适用于高度类别不平衡的细粒度分割场景。与传统的区域型损失(如Dice、交叉熵)不同,它通过计算预测边界与真实边界之间的距离来优化模型,更关注边界精度而非区域重叠。核心思想是利用距离图(distance map)将边界约束转化为区域积分形式,实现端到端训练。具体实现中,损失函数为预测概率与距离图的点积,梯度仅取决于距离图,具有明确的空间引导性。相比区域型损失,Boundary Loss能更好处理小目标、细长结构等边界敏感任务,可与Dic

悦学共鸣,温柔以待,汇聚光芒,共同成长 240

java await signal_java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)...

一、Condition 类在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的java.util.concurrent.locks.ReentrantLock 锁,JDK也为我们提供了与此功能相应的类java.util.concurrent.locks.Condition。Condition与重入锁是...

weixin_39699070的博客 364

将Keil中的变量数组导出

首先,写好导出数据的函数。

小柚子的博客 1952

FLUENT 软件中design modeler网格划分后,导出失败:系统显示“在网格文件导出过程中出现异常。请将数据发送给您的技术支持供应商。”...如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1472

poi 在空白文档 创建页眉页脚_如何使用Office Word进行文档排版?

如何使用Office Word进行文档排版?如果喜欢本文的话,请点击关注。为了鼓励作者创作,请顺手点击文中的广告,您的支持,是我创造的动力。我们在工作中经常会用到Microsoft Office软件中的Word进行文档编辑。简单的文字编辑,大家基本上都会,基本的排版也是没有问题,但是一旦文档较大,例如上百页的文档,需要更改一些格式时,尤其是批量进行格式修改时,对于较大文档一个一个修改的话就比较麻烦...

weixin_39769740的博客 659

【全志V821_FoxPi】6-2 IMX219 MIPI摄像头适配

全志V821芯片适配IMX219 MIPI摄像头(2lane)教程,基于FoxPi开发板V1.2 SDK。文章详细介绍了IMX219的技术参数(800万像素、1/4英寸CMOS、支持1080P@30fps输出)及模组接口原理图。重点展示了设备树配置方法,包括PIO引脚定义(TWI0使用PA3/PA4,复位引脚PA2)、TWI0节点设置(100kHz时钟)以及VIND0节点中sensor0的完整配置(I2C地址0x20、MCLK0、RAW格式输出等)。配置过程强调需注意IMX219的器件地址转换(0x10→0

第四维度的博客 2252

【Java】Lock锁的细节内容-ORA-00060: 等待资源时检测到死锁

代码中如何正确使用Lock锁

weixin_42369773的博客 1482

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Java8 Lock锁详解(AQS,CAS)

什么是Lock锁? Lock锁提供了的比synchronized关键字更加灵活的锁操作,是代码层面的锁操作。 为什么要使用Lock锁? Lock锁和synchronized关键字的对比 类型 synchronized关键字 Lock锁 获取锁 无超时时间,未获取到则阻塞等待(占用cpu资源),且无法被中断 非阻塞,可以被中断,未获取到则排队,中断,可以自定义超时时间 共享锁 不支持 读写锁ReadWriteLock支持 释放锁 必须在当前代码块中,因为synchronized是以{

Leetp 4268

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

java中Lock锁实现原理

java中Lock锁实现原理

SO_zxn的博客 1273

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

从零开始java多线程到分布式锁(十一):Lock的基本概念

一:java中的锁 java中的锁关键字分为3种:Lock、Synchronized以及volatile。 1 .Lock和Synchronized区别 Lock: 为java中的显示锁,锁的获取和释放可以在不同的 Synchronized:为java中隐石锁,所得获取和释放是在同步代码块的开始结束位置,是java实现同步的最简单的方法。 2.Synchron...

qq_35755863的博客 320

Java中Lock(synchronized和lock区别)

Java中Lock(synchronized和lock区别) 首先我们要明白,lock锁是后出的(1.5),肯定是弥补了部分的不足,一起认识下他们的区别 synchronized是内置的关键字(功能统一),Lock锁是一个类,在java.util.concurrent.locks下的(功能可以改变的)。 由于synchronized是悲观锁,他会一直等等待对象头锁信息,阻塞的,不可被打断的。而Lock可以判断是否获取锁,并且可以不一定等待获取到锁。可以结束自己 synchronized是自动上锁和自动释

三少说 1364

Java 中的锁之Lock接口

锁是控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但是有些锁是允许多个并发线程的访问,如读写锁),在Lock接口出现之前,Java程序靠synchronized关键字实现锁功能的。Java SE5之后,并发包里增加了Lock 接口(以及相关实现类)用来实现锁功能,提供类似的同步功能,缺少synchronized 隐身释放锁的便捷性,但是拥有锁的获取与释放的可操作...

jcsyl_mshot的博客 549

深入浅出 Java Concurrency (8): 加锁的原理 (Lock.lock)

深入浅出 Java Concurrency (8): 加锁的原理 (Lock.lock) 接上篇,这篇从Lock.lock/unlock开始。特别说明在没有特殊情况下所有程序、API、文档都是基于JDK 6.0的。 public void java.util....

150

Java锁详解(一)------ lock的实现

一、Lock与Synchronized的区别 Lock是个接口,有如下方法: lock():获取锁 lockInterruptibly():可中断的获取锁,与lock()不同的点是该方法会响应中断(锁获取中,可中断当前县城) tryLock(): 非阻塞获取锁,...

chouse10938的博客 314

Java中的锁 Lock和synchronized

Java中的锁 Lock和synchronized一、Java中的锁机制及Lock类锁的释放-获取建立的happens before 关系锁释放和获取的内存语义锁内存语义的实现二、concurrent包的实现三、synchronized实现原理1、实现原理2、Java对象头3、Monitor4、锁优化5、自旋锁6、适应自旋锁7、锁消除8、锁粗化9、轻量级锁10、偏向锁11、重量级锁 一、Java中的锁机制及Lock类 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步

qq_40959750的博客 852

java中的锁---Lock

参考:https://www.cnblogs.com/cl1024cl/p/6205013.html https://www.cnblogs.com/myseries/p/10784076.html https://blog.youkuaiyun.com/caideb/article/details/85289790 https://blog.youkuaiyun.com/luxia_24/article/details/52403033 https://blog.youkuaiyun.com/qq_37997523/article/deta

Fuly的博客 312

Lock的锁之优化

Lock / synchronized Lock锁的基本操作是通过乐观锁实现的,由于Lock锁也会在阻塞时被挂起,依然属于悲观锁 synchronizedLock实现方式JVM层实现Java底层代码实现锁的获取JVM隐式获取lock() / tryLock() / tryLock(timeout, unit) / lockInterruptibly()锁的释放JVM隐式释放unlock()锁的类型...

春来桃花开的博客 320

Lock锁源码分析

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34189116的博客 102

java中的锁

1、锁的概述     锁,是对权限的控制。在生活中,有门锁,电子锁;数据库中有数据库行锁、表锁;Java中也有对应的锁。     java中锁的实现方式有两种,一种是jvm底层提供的关键字synchronized,一种是jdk提供的api定义了锁接口Lock,可以通过实现Lock接口来实现自定义锁。 2、Java锁的使用场景     在Java编程中,为了对CPU的充分利用,需要并发的执行程序功能...

weixin_42397611的博客 243
上一篇: CountDownLatch问题汇总
下一篇: Java 生产者消费者代码
予亭
博客等级 码龄12年 167粉丝 216原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值