并发编程(六)ReentrantLock

简介: 并发编程(六)ReentrantLock

Java并发编程核心在于java.concurrent.util

juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer简称AQSAQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态(state)的同步器。

AQS具备特性

  • 阻塞等待队列
  • 共享/独占
  • 公平/非公平
  • 可重入
  • 允许中断

ReentrantLock

ReentrantLock定义了一个内部类Sync继承了AQS,通过这种方式将同步器所有调用都映射到Sync对应的方法,同时ReentrantLock也具备AQS的特性。ReentrantLock具备以下特性

  • 阻塞等待队列
  • 独占
  • 公平/非公平
  • 可重入
  • 允许中断

ReentrantLock继承关系

ReentrantLock里面定义了三个内部类SyncFairSyncNonfairSyncFairSyncNonfairSync表示公平锁与非公平锁,通过这两个内部类实现公平与非公平的机制,具体关系如下图:

Lock.png

FairSyncNonfairSync是通过继承Sync实现的,其中FairSync加锁机制为先判断列队中是否有其它线程正在等待加锁,如果有则直接入队,没有才会尝试加锁;而NonfairSync加锁机制为先进行尝试加锁,加锁失败才进行入队。

除此之外,ReentrantLock还可通过lockInterruptibly()加锁时可使用Thread.interrupt()进行中断加锁过程。

ReentrantLock加锁过程(简述)

ReentrantLock加锁详细过程

公平锁加锁过程

  1. 查看队列中是否有其它线程等待加锁
  2. 队列为空或者等待加锁的线程为当前线程,尝试CAS加锁
  3. 加锁成功 state+1,结束
  4. 加锁失败(只发生在队列为空的情况),或者队列不为空且等待加锁的线程非当前线程,进行入队。
  5. 入队完毕,将前驱结点信号量(waitStatus)改为-1,阻塞等待LockSupport.park(this)

解锁过程

  1. 解锁state-1
  2. 判断state==0(可重入锁,每次加锁state都会+1,释放锁次数必须等于加锁次数才算已解锁)
  3. 判断队列中是否有等待加锁的线程
  4. 将线程唤醒LockSupport.unpark(thread)

ReentrantLocksynchronized比较

  1. 加锁机制比较
  • ReentrantLock,基于AQS实现的锁,需要手动加锁解锁,细粒度和灵活度更高
  • synchronizedJVM内部锁,JVM会自动加锁与解锁
  1. 底层原理比较
  • 都是依赖底层操作系统的Mutex lock(互斥锁)实现
  1. 锁类型比较
  • synchronized是一种可重入的非公平锁
  • ReentrantLock是基于AQS实现,具体特性上文已有说明
  1. 性能比较(未实测)
  • 在并发量小时,synchronized性能更高一些
  • 并发量高时,synchronized性能将会下降(升级为重量级锁),而ReentrantLock基本不变。

我这里的理解是,synchronizedReentrantLock底层阻塞原理虽然是一样的,而ReentrantLock利用CAS自旋操作实现锁,能够有效避免线程从用户态到内核态的频繁切换。

目录
相关文章
|
存储 安全
并发编程——ReentrantReadWriteLock
因为ReentrantLock是互斥锁,如果有一个操作是读多写少,同时还需要保证线程安全,那么使用ReentrantLock会导致效率比较低。因为多个线程在对同一个数据进行读操作时,也不会造成线程安全问题。
32 0
|
Java
Java并发编程:使用CountDownLatch实现线程同步
在Java并发编程中,线程同步是一个重要的概念。当多个线程需要协调工作或者共享资源时,我们需要使用一些机制来确保线程的有序执行。
178 1
|
3月前
|
消息中间件 存储 监控
Java并发知识之ReentrantLock
本文深入剖析了Java中并发编程的核心概念,特别聚焦于锁的设计思想,通过分析AbstractQueuedSynchronizer(AQS)、ReentrantLock和ReentrantReadWriteLock的实现,揭示了锁的工作原理和高效并发控制策略。
Java并发知识之ReentrantLock
|
3月前
|
安全 Java
Java并发编程实战:使用synchronized和ReentrantLock实现线程安全
【8月更文挑战第31天】在Java并发编程中,保证线程安全是至关重要的。本文将通过对比synchronized和ReentrantLock两种锁机制,深入探讨它们在实现线程安全方面的优缺点,并通过代码示例展示如何使用这两种锁来保护共享资源。
|
6月前
|
安全 Java 程序员
Java并发编程:理解并应用ReentrantLock
【4月更文挑战第30天】 在多线程的世界中,高效且安全地管理共享资源是至关重要的。本文深入探讨了Java中的一种强大同步工具——ReentrantLock。我们将从其设计原理出发,通过实例演示其在解决并发问题中的实际应用,以及如何比传统的synchronized关键字提供更灵活的锁定机制。文章还将讨论在使用ReentrantLock时可能遇到的一些挑战和最佳实践,帮助开发者避免常见陷阱,提高程序性能和稳定性。
|
6月前
|
安全 Java 程序员
Java多线程基础-17:简单介绍一下JUC中的 ReentrantLock
ReentrantLock是Java并发包中的可重入互斥锁,与`synchronized`类似但更灵活。
53 0
|
Java
并发编程——ReentrantLock
Java中提供锁,一般就是synchronized和lock锁,ReentrantLock跟synchronized一样都是互斥锁。如果竞争比较激烈,推荐lock锁,效率更高。如果几乎没有竞争,推荐synchronized。
28 0
|
存储 缓存 安全
并发编程——synchronized
原子性、有序性、可见性
43 0
|
Java
多线程和并发编程(3)—AQS和ReentrantLock实现的互斥锁
多线程和并发编程(3)—AQS和ReentrantLock实现的互斥锁
101 0
|
Java 开发者
并发编程(五)synchronized
并发编程(五)synchronized
146 0