首页 > 其他分享 >深入探索ReentrantLock(四):公平与非公平锁的双重奏

深入探索ReentrantLock(四):公平与非公平锁的双重奏

时间:2024-11-13 10:49:32浏览次数:3  
标签:task Thread ReentrantLock 线程 公平 与非 new

前言

在并发编程中,锁是管理共享资源访问的关键机制之一。Java并发包(java.util.concurrent)中的ReentrantLock类提供了一个比内置synchronized关键字更灵活的锁实现。它不仅支持重入性(即同一个线程可以多次获得锁),还提供了公平锁和非公平锁两种模式,以满足不同场景下的需求。本文将深入探讨这两种锁模式的差异、应用场景以及性能考量。


一、ReentrantLock非公平锁

1.介绍

在并发编程领域,非公平锁作为锁机制的一种重要形式,尤其在Java的ReentrantLock类中,被设定为默认模式。非公平锁的设计哲学在于,它并不遵循严格的先进先出(FIFO)原则来分配锁资源。当锁被当前持有者释放时,系统不会依据线程请求锁的顺序来授予锁,而是允许任何正在尝试获取该锁的线程直接参与竞争,锁的分配更多地依赖于线程的调度策略和操作系统的即时状态。这种机制可能导致所谓的“插队”现象,即新到达的线程可能先于长时间等待的线程获得锁,从而增加了锁获取的不确定性。

// 创建ReentrantLock实例,等同于使用ReentrantLock(false)
ReentrantLock lock = new ReentrantLock();

源码如下:

2.优点与适用场景

优点解析

  • 高性能:非公平锁的核心优势在于其高效性。由于无需维护一个严格的等待队列,并减少了对队列操作的开销(如入队、出队、排序等),这使得非公平锁在大多数并发场景下能够展现出更优的性能表现。特别是在高并发环境中,减少这些额外操作可以显著提升系统的整体吞吐量。
  • 简单高效:从实现角度来看,非公平锁的设计更为简洁,减少了系统资源的消耗。它直接利用操作系统的线程调度机制来管理锁的分配,避免了复杂的队列管理逻辑,从而提高了系统的运行效率。
  • 灵活性:在某些应用场景中,锁的获取顺序并非关键因素,而系统的响应速度和吞吐量更为重要。非公平锁提供了这种灵活性,允许系统根据当前的实际情况快速响应,而不必拘泥于严格的顺序要求。

适用场景

  • 对锁获取顺序不敏感的场景:在这些场景中,锁的主要作用是保护共享资源,防止数据竞争,而锁的获取顺序并不会对业务逻辑产生显著影响。
  • 高性能要求的应用:在对响应时间有严格要求的系统中,如实时交易系统、高频交易系统等,非公平锁能够凭借其高效性优势,帮助系统实现更快的响应速度和更高的吞吐量。
  • 高并发环境:在高并发场景下,系统的负载较重,维护一个有序的等待队列可能会成为性能瓶颈。此时,采用非公平锁可以有效减轻系统的负担,提升系统的整体性能。

3.案例

以下示例展示了ReentrantLock非公平锁在实际应用中的使用效果。

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {

    public static void main(String[] args) {
        Task task = new Task();
        new Thread(task, "Thread-1").start();
        new Thread(task, "Thread-2").start();
        new Thread(task, "Thread-3").start();
        new Thread(task, "Thread-4").start();
        new Thread(task, "Thread-5").start();
    }
}

class Task implements Runnable {

    // 非公平锁
    ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {
            lock.lock();
            System.out.println(name + " 已获得锁");
        } finally {
            lock.unlock();
        }
    }
}

运行结果:

二、ReentrantLock公平锁

1.介绍

公平锁是一种并发控制机制,旨在确保在多线程环境中,所有请求锁的线程都能按照它们请求锁的顺序来获得锁,从而避免了线程间的饥饿现象。在ReentrantLock类中,当构造函数被显式地设置为true时,该锁即进入公平锁模式。这一模式下,系统内部维护了一个FIFO(先进先出)的等待队列,严格按照线程请求锁的顺序来管理和分配锁资源。

// 使用给定的公平性策略创建ReentrantLock实例,如果形参fair为true,这个锁使用一个公平的排序策略
ReentrantLock lock = new ReentrantLock(true);

源码如下:

2.优缺点与适用场景

优点解析

  • 公平性保证:公平锁的核心优势在于其严格的锁分配策略,确保了所有等待的线程都有平等的机会获得锁,从而有效防止了“饥饿”线程的出现,即某些线程因长时间无法获得锁资源而导致执行延迟或停滞。
  • 可预测性增强:在需要高度确定性和可预测性的系统设计中,公平锁能够提供一个稳定且可预测的锁获取顺序,这对于维持系统的稳定性和提高调试效率至关重要。特别是在需要严格控制任务执行顺序的场景中,公平锁的优势尤为明显。

缺点剖析

  • 性能开销增大:尽管公平锁带来了诸多优势,但其实现机制也带来了额外的性能负担。每次锁释放时,系统都需要执行复杂的队列操作以确保锁的公平分配,这不可避免地增加了系统的响应时间和整体开销。
  • 资源消耗增加:为了维护有序的等待队列,公平锁需要额外的数据结构和复杂的逻辑处理来管理队列中的线程。这些额外的数据结构(如链表或队列)和相应的算法实现,都会增加系统的内存占用和CPU消耗,从而可能影响系统的整体性能。

适用场景

  • 高度依赖公平性的业务场景:在需要确保线程公平访问共享资源的业务逻辑或算法实现中,公平锁是不可或缺的工具。例如,金融交易系统、票务预订系统等,都需要保证操作的公平性和有序性。
  • 调试与测试阶段:在软件开发的调试和测试阶段,公平锁可以帮助开发者更准确地分析锁竞争和死锁等问题。通过模拟和观察线程间的锁请求和获取过程,开发者可以更容易地定位和修复潜在的并发问题。

3.案例

以下示例展示了ReentrantLock公平锁在实际应用中的使用效果。

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {

    public static void main(String[] args) {
        Task task = new Task();
        new Thread(task, "Thread-1").start();
        new Thread(task, "Thread-2").start();
        new Thread(task, "Thread-3").start();
        new Thread(task, "Thread-4").start();
        new Thread(task, "Thread-5").start();
    }
}

class Task implements Runnable {

    // 公平锁
    ReentrantLock lock = new ReentrantLock(true);

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {
            lock.lock();
            System.out.println(name + " 已获得锁");
        } finally {
            lock.unlock();
        }
    }
}

运行结果:


总结

选择ReentrantLock的公平锁或非公平锁模式是一项需要综合考虑多方面因素的决策,开发者应根据实际应用的需求、性能要求以及系统负载的波动,灵活调整锁的策略,并结合合理的并发设计,来构建高效、稳定的并发应用。本文主要介绍了ReentrantLock的公平锁与非公平锁,助力开发者构建高效稳定的并发应用。

标签:task,Thread,ReentrantLock,线程,公平,与非,new
From: https://blog.csdn.net/jiangyq_/article/details/142182232

相关文章

  • 非制冷红外探测器驱动模块设计与非均匀校正实现
     文章目录第一章 非制冷红外探测器性能简介第二章非制冷红外探测器驱动模块设计第三章非制冷红外探测器驱动模块状态机设计第四章非制冷红外探测器非均匀校正参数的获取与存储第五章OOC参数和两点校正KB参数的上电加载使用总结第一章 非制冷红外探测器性能简介......
  • 深入探索ReentrantLock(三):限时锁申请的艺术
     专栏导航JVM工作原理与实战RabbitMQ入门指南从零开始了解大数据目录前言一、ReentrantLock限时锁申请1.限时锁申请的必要性2.tryLock(longtime,TimeUnitunit)方法讲解3.限时锁的优势与注意事项4.tryLock(longtime,TimeUnitunit)案例总结前言Java并发......
  • 【论文分享】是时候挑战15分钟城市了:可持续发展、公平性、宜居和空间分析的七个缺陷
    15分钟城市,目标是与城市生活有关的场所,都在步行或骑行“15分钟圈”内。本次带来一篇论文的全文翻译,从理论和空间分析角度,探讨了15分钟城市存在的七个缺陷,旨在重新定位15分钟城市,以期更好得改善环境和社会成果,让城市能够实现可持续发展、公平宜居的目标。【论文题目】Timeto......
  • 深入探索ReentrantLock(二):解锁中断响应机制
     专栏导航JVM工作原理与实战RabbitMQ入门指南从零开始了解大数据目录前言一、ReentrantLock中断响应机制1.lockInterruptibly()方法讲解2.lockInterruptibly()相比于lock()的优势3.lockInterruptibly()案例总结前言Java并发编程中,ReentrantLock作为可重入互斥......
  • 【漏洞复现】致远互联 FE协作办公平台 fillKP.jsp SQL注入漏洞
    免责声明:        本文旨在提供有关特定漏洞的信息,以帮助用户了解潜在风险。发布此信息旨在促进网络安全意识和技术进步,并非出于恶意。读者应理解,利用本文提到的漏洞或进行相关测试可能违反法律或服务协议。未经授权访问系统、网络或应用程序可能导致法律责任或严......
  • 如何实现企业薪酬管理的内部公平和外部公平?
    如何实现企业薪酬管理的内部公平和外部公平?薪酬体系,作为企业管理中不可或缺的核心议题,直接触及每位员工的切身利益与心理感知,其公正性构建更是企业稳健发展的基石。在人力资源管理的广阔图景中,薪酬制度不仅是员工感知组织公平性的晴雨表,更是激发潜能、促进团队和谐的关键杠杆......
  • 并发编程中锁Synchronized和ReentrantLock,CAS,AQS理解
    SynchronizedJAVA关键字,独占式的悲观锁,可重入锁。主要解决多个线程之间的访问资源的同步性,可以保证被他修饰的方法或者代码块在任意时刻只能有一个线程执行早期是重量级锁,JAVA6后引入大量优化,自旋锁,适应性自旋锁,偏向锁,轻量级锁,锁消除,锁粗化减少锁的开销使用方式修饰......
  • Synchronized锁和Reentrantlock的区别和联系以及锁升级
    二者的底层实现:Synchronized就是基于monitor对象主要的为Owner获得这个锁资源的线程唯一标识符(线程ID)Count线程获得几次锁(可重入锁的实现)ContentionList等待队列(线程加锁失败的情况下)Reentrantlock是基于AQS这个就是表示是哪一个线程获得这个锁资源    ......
  • Vavr - java函数式编程,分离业务代码与非业务代码神器
    微信公众号:阿俊的学习记录空间小红书:ArnoZhangwordpress:arnozhang1994博客园:arnozhangCSDN:ArnoZhang19941.入门指南使用Vavr的项目至少需要支持Java1.8。该.jar文件可以在MavenCentral获取。1.1.Gradledependencies{compile"io.vavr:vavr:0.10.4"}G......
  • 简单说说 ReentrantLock
            ReentrantLock底层依赖AQS进行实现,是一种可重入的锁。        在ReentrantLock中实现公平锁和非公平锁。        在公平锁中,当调用lock方法,会先判断队列是否存在等待中的节点,如果队列无节点,会尝试去获取锁,如果获取到了锁,则执行业务代码,如果......