线程安全往往需要靠互斥锁机制来保证,ReentrantLock是比关键字sychronized更灵活的可重入互斥锁。ReentrantLock在不使用锁(它自己本身就是Lock)和synchronized关键字的前提下,是怎么保证线程安全的呢。
看一下不公平锁实现的lock方法(调用的是Sync(NonfairSync)的lock方法
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)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
1. 先通过CAS原子操作来试图获取锁(当前状态==0并且成功的将状态改为1),如果CAS返回true,说明成功获取到锁,那么简单的将该锁的拥有线程设为当前线程即可返回。锁获取成功。
2. 如果CAS返回false,则调用acquire方法,其中先调用tryAcquire方法,在不公平锁的实现中,tryAcuqire方法首先做的操作与lock方法的第一步操作基本重复,也是先通过CAS原子操作尝试获取锁,成功则设置所谓当前线程所有。如果当前的状态不为0(说明有线程已经获取到该锁),则判断持有该锁的是不是当前线程自身,如果是自身,由于是可重入锁,则简单的将当前状态计数+1就可返回,锁获取成功。
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
//tryAcquire /** * Performs non-fair tryLock. tryAcquire is * implemented in subclasses, but both need nonfair * try for trylock method. */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
3. 如果不是上面这2种情况,则说明锁已经被其他线程排他占用,则调用addWaiter先将当前线程放入等待队列中,然后在acquireQueued方法中,循环判断是否已经轮到当前节点(即该节点前面没有可用节点),如果没有有效节点,则再尝试调用tryAcquire方法,失败则继续循环,否则成功获取到锁并返回。如果前面有其他节点,则将当前线程park,当前线程阻塞,可能直到其他线程unlock调用unpark,然后才恢复执行并重新试图获取该锁。
//this method is implemented in AbstractQueuedSynchronizer /** * Acquires in exclusive uninterruptible mode for thread already in * queue. Used by condition wait methods as well as acquire. * * @param node the node * @param arg the acquire argument * @return {@code true} if interrupted while waiting */ final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
相关推荐
1、ReentrantLock简介 2、ReentrantLock函数列表 3、重入的实现 4、公平锁与非公平锁 5、ReentrantLock 扩展的功能 6
ReentrantLock 实现原理 1
本文将对ReentrantLock实现原理进行详细的介绍,具有很好的参考价值,下面跟着小编一起来看下吧
java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能。而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。这篇文章主要是从使用的角度来分析...
第六章 ReentrantLock源码解析2--释放锁unlock()最常用的方式://注意:通常情况下,这个会设置成一个类变量,比如说Segement中的段锁
主要介绍了ReentrantLock源码之条件锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来一起学习一下吧
第五章 ReentrantLock源码解析1--获得非公平锁与公平锁lock()最常用的方式://注意:通常情况下,这个会设置成一个类变量,比如说Segemen
ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。下面我们来深入了解一下它吧
Locks 框架提供了比传统的 synchronized 关键字更强大、更灵活的线程同步机制,而 ReentrantLock 是其中的一种重要实现。 Locks 框架概述: 简要介绍 Locks 框架,解释其在多线程编程中的作用和优势。比较 Locks ...
4、ReentrantLock底层实现和如何使用 5、Condition源码分析 6、ReentrantReadWriteLock底层实现原理 7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、...
java语言 并发编程 ReentrantLock与synchronized区别 详解
可重入锁: 也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,...ReentrantLock 在Java也是一个基础的锁,ReentrantLock 实现Lock接口提供一系列的基础函数,开发人员可以灵活的是应用函数满足各种复杂多变应用场景;
ReentrantLock的使用及注意事项
Java 多线程与并发(11_26)-JUC锁_ ReentrantLock详解
助于理解的例子 博文链接:https://uule.iteye.com/blog/1488356
1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用...那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平
ReentrantLock源码剖析
一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个...
带你看看Javad的锁-ReentrantLock前言ReentrantLock简介Synchronized对比用法源码分析代码结构方法分析SyncNonfairSyncFairSync非公平锁VS公平锁什么是公平非公平ReentrantLockReentrantLock的构造函数lock加锁方法...
近日,阅读jdk并发包源码分析整理笔记。