ReentrantLock.unLock():锁的释放
public void unlock() { sync.release(1);//AQS }
AbstractQueuedSynchronizer.release()
public final boolean release(int arg) { if (tryRelease(arg)) {//尝试释放锁,子类实现 Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h);//唤醒后继节点 return true; } return false; }
若 tryRelease(arg)释放锁成功(state==0);则考虑唤醒AQS中的下一个节点,前提:队列不为空,AQS队列的头结点需要锁(waitStatus!=0),如果头结点需要锁,就开始检测下一个继任节点是否需要锁操作。
waitStatus含义
ReentrantLock.Sync.tryRelease(int releases)
protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread())//持有锁的线程不是当前线程,抛出异常。(线程锁只有拥有锁的线程才能释放) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) {//state = 0:表示当前线程已经释放了锁,锁处于空闲状态.因为ReetrantLock可重入,maybe c>0 free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
AbstractQueuedSynchronizer.unparkSuccessor(Node node)
private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ int ws = node.waitStatus; if (ws < 0)//当前node已经释放锁了,状态设置为0 compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ //从头结点的下一个节点开始寻找继任节点,当且仅当继任节点的waitStatus<=0才是有效继任节点,否则将这些waitStatus>0(也就是CANCELLED的节点)从AQS队列中剔除 //这里并没有从head->tail开始寻找,而是从tail->head寻找最后一个有效节点。 //解释在这里 http://www.blogjava.net/xylz/archive/2010/07/08/325540.html#377512 Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }
这里再一次把acquireQueued的过程找出来。对比unparkSuccessor,一旦头节点的继任节点被唤醒,那么继任节点就会尝试去获取锁(在acquireQueued中node就是有效的继任节点,p就是唤醒它的头结点),如果成功就会将头结点设置为自身,并且将头结点的前任节点清空,这样前任节点(已经过时了)就可以被GC释放了。 final boolean acquireQueued(final Node node, int arg) { try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } catch (RuntimeException ex) { cancelAcquire(node); throw ex; } }
参考:http://www.blogjava.net/xylz/archive/2010/07/08/325540.html
相关推荐
Java并发编程中的ReentrantLock是Java并发包(java.util.concurrent,简称JUC)中的一个重要的锁机制,它是Lock接口的一个具体实现,提供了比synchronized更强大的锁定功能和更细粒度的控制。ReentrantLock的主要...
Java中的ReentrantLock是Java并发包(java.util.concurrent.locks)中的一个高级锁,它是可重入的,意味着一个线程可以多次获取同一锁。在深入ReentrantLock之前,我们首先需要了解Java并发编程的基础,特别是Java...
Java并发编程领域中的JUC(Java Util Concurrency)是一门深奥且实用的技术,它包含在Java的`java.util.concurrent`包中,为多线程编程提供了高效、易用的工具。这个压缩包文件“个人学习JUC代码笔记总集”显然是一...
JUC中的锁机制包括ReentrantLock(可重入锁)、ReadWriteLock(读写锁)等。ReentrantLock相比synchronized具有更细粒度的控制,支持公平性和非公平性,并提供了tryLock()方法来尝试获取锁,以及lockInterruptibly...
JUC也提供了一系列的锁实现,比如ReentrantLock,它提供了比synchronized更灵活的锁控制机制。ReentrantLock支持尝试非阻塞地获取锁、可中断地获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。 ...
3. **JUC核心API**:重点学习JUC包中的核心API,如`ReentrantLock`、`Condition`、`CountDownLatch`等。 4. **实战项目**:通过实际项目练习来巩固所学知识,例如实现一个基于线程池的任务调度系统或一个高并发的...
2. **锁机制**:JUC提供了显式锁ReentrantLock,它比synchronized更灵活,支持公平锁和非公平锁,以及可中断和可重入的特性。此外,还有读写锁ReentrantReadWriteLock,允许多个读取者同时访问,但只允许一个写入者...
- `ReentrantLock`是`Lock`接口的主要实现之一,支持公平锁和非公平锁,以及可中断的锁定机制。 3. **基本售票示例**: - 使用`ReentrantLock`实现售票系统可以有效地控制对资源的访问,避免线程间的冲突。 - ...
2. **锁**:除了基本的`synchronized`关键字外,JUC还提供了更灵活的锁机制,如`ReentrantLock`等。 3. **同步器**:如`Semaphore`、`CountDownLatch`、`CyclicBarrier`等,它们可以帮助解决复杂的同步问题。 4. **...
- **ReentrantLock**:可重入锁,功能比synchronized更强大,具有公平性、非公平性选择,以及更细粒度的锁获取和释放控制。 4. **并发容器**: - **ConcurrentHashMap**:线程安全的哈希表,比synchronized的...
"JUC底层讲解,面试可用" JUC是Java并发编程的API,java.util.concurrent包名的简写。JUC相关的包有三个:java.util.concurrent、java.util.concurrent.atomic、java.util.concurrent.locks。 并发编程相关概念: ...
3. **locks**:此包提供了高级锁定机制,如`ReentrantLock`和`ReadWriteLock`,比内置的`synchronized`关键字更灵活,可以实现更复杂的同步策略。 在学习JUC的过程中,你需要理解以下关键概念: - **线程池**:...
⼀、ReentrantLock重⼊锁 1.1> 概述 1.2> 中断响应 lockInterruptibly() 1.3> 锁申请等待限时 tryLock(long time, TimeUnit unit) 1.4> 公平锁和⾮公平锁 1.5> AQS源码解析 ⼆、Condition重⼊锁的搭配类 三、...
### JUC并发编程知识点 #### 1. 进程与线程 - **进程**: 进程是指正在运行中的程序实例。每个进程都有自己独立的内存空间,并且一个进程中可以包含多个线程。例如,当你打开QQ应用时,就启动了一个进程。 - **线程...
在Java并发编程中,"JUC个人笔记1"主要探讨了多线程并发控制的一些核心概念和技巧。首先,遵循高内聚低耦合的原则,将线程的操作与资源类进行解耦,使得代码结构更加清晰,易于维护。在多线程交互中,特别是涉及到`...
8. Lock接口 (ReentrantLock 可重入锁) 特性 ReentantLock 继承接口 Lock 并实现了接口中定义的方法, 它是一种可重入锁, 除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁...
### JUC并发编程中的虚假唤醒及其解决方案 #### 一、虚假唤醒的概念与原理 在Java并发编程中,尤其是在处理多线程同步时,一个重要的概念是“虚假唤醒”(Spurious Wakeup)。这是一种较为罕见的现象,但在实际...
除了volatile,Java还提供了Lock接口及其实现,如ReentrantLock(可重入锁),支持公平/非公平策略,以及ReentrantReadWriteLock(读写锁),允许多个读取者同时访问,但写入者与其他所有线程互斥。 总之,理解和...