@@ -16,39 +16,40 @@ tags:
1616<!-- TOC depthFrom:2 depthTo:4 -->
1717
1818- [ 概述] ( #概述 )
19- - [ 概念] ( #概念 )
20- - [ 公平锁/非公平锁] ( #公平锁非公平锁 )
21- - [ 可重入锁] ( #可重入锁 )
22- - [ 独享锁/共享锁] ( #独享锁共享锁 )
23- - [ 互斥锁/读写锁] ( #互斥锁读写锁 )
24- - [ 乐观锁/悲观锁] ( #乐观锁悲观锁 )
25- - [ 分段锁] ( #分段锁 )
26- - [ 偏向锁/轻量级锁/重量级锁] ( #偏向锁轻量级锁重量级锁 )
27- - [ 自旋锁] ( #自旋锁 )
28- - [ 为什么用 Lock、ReadWriteLock] ( #为什么用-lockreadwritelock )
19+ - [ 概念] ( #概念 )
20+ - [ 公平锁/非公平锁] ( #公平锁非公平锁 )
21+ - [ 可重入锁] ( #可重入锁 )
22+ - [ 独享锁/共享锁] ( #独享锁共享锁 )
23+ - [ 互斥锁/读写锁] ( #互斥锁读写锁 )
24+ - [ 乐观锁/悲观锁] ( #乐观锁悲观锁 )
25+ - [ 分段锁] ( #分段锁 )
26+ - [ 偏向锁/轻量级锁/重量级锁] ( #偏向锁轻量级锁重量级锁 )
27+ - [ 自旋锁] ( #自旋锁 )
28+ - [ 为什么用 Lock、ReadWriteLock] ( #为什么用-lockreadwritelock )
2929- [ Lock 和 ReentrantLock] ( #lock-和-reentrantlock )
30- - [ 要点] ( #要点 )
31- - [ 源码] ( #源码 )
32- - [ Lock] ( #lock )
33- - [ ReentrantLock] ( #reentrantlock )
34- - [ 示例] ( #示例 )
30+ - [ 要点] ( #要点 )
31+ - [ 源码] ( #源码 )
32+ - [ Lock 接口定义] ( #lock-接口定义 )
33+ - [ ReentrantLock 属性和方法] ( #reentrantlock-属性和方法 )
34+ - [ Sync] ( #sync )
35+ - [ 示例] ( #示例 )
3536- [ ReadWriteLock 和 ReentrantReadWriteLock] ( #readwritelock-和-reentrantreadwritelock )
36- - [ 要点] ( #要点-1 )
37- - [ 源码] ( #源码-1 )
38- - [ ReadWriteLock] ( #readwritelock )
39- - [ 示例] ( #示例-1 )
37+ - [ 要点] ( #要点-1 )
38+ - [ 源码] ( #源码-1 )
39+ - [ ReadWriteLock 接口定义 ] ( #readwritelock-接口定义 )
40+ - [ 示例] ( #示例-1 )
4041- [ AQS] ( #aqs )
41- - [ 要点] ( #要点-2 )
42- - [ 源码] ( #源码-2 )
43- - [ 同步队列] ( #同步队列 )
44- - [ 获取独占锁] ( #获取独占锁 )
45- - [ 释放独占锁] ( #释放独占锁 )
46- - [ 获取可中断的独占锁] ( #获取可中断的独占锁 )
47- - [ 获取超时等待式的独占锁] ( #获取超时等待式的独占锁 )
48- - [ 获取共享锁] ( #获取共享锁 )
49- - [ 释放共享锁] ( #释放共享锁 )
50- - [ 获取可中断的共享锁] ( #获取可中断的共享锁 )
51- - [ 获取超时等待式的共享锁] ( #获取超时等待式的共享锁 )
42+ - [ 要点] ( #要点-2 )
43+ - [ 源码] ( #源码-2 )
44+ - [ 同步队列] ( #同步队列 )
45+ - [ 获取独占锁] ( #获取独占锁 )
46+ - [ 释放独占锁] ( #释放独占锁 )
47+ - [ 获取可中断的独占锁] ( #获取可中断的独占锁 )
48+ - [ 获取超时等待式的独占锁] ( #获取超时等待式的独占锁 )
49+ - [ 获取共享锁] ( #获取共享锁 )
50+ - [ 释放共享锁] ( #释放共享锁 )
51+ - [ 获取可中断的共享锁] ( #获取可中断的共享锁 )
52+ - [ 获取超时等待式的共享锁] ( #获取超时等待式的共享锁 )
5253- [ 资料] ( #资料 )
5354
5455<!-- /TOC -->
@@ -145,85 +146,65 @@ synchronized void setB() throws Exception{
145146
146147### 要点
147148
148- ReentrantLock 实现了 Lock 接口,所以支持 Lock 的所有方法。
149+ 如果采用 Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用 Lock 必须在 try catch 块中进行,并且将释放锁的操作放在 finally 块中进行,以保证锁一定被被释放,防止死锁的发生。
150+
151+ ` lock() ` 方法的作用是获取锁。如果锁已被其他线程获取,则进行等待。
152+
153+ ` tryLock() ` 方法的作用是尝试获取锁,如果成功,则返回 true;如果失败(即锁已被其他线程获取),则返回 false。也就是说,这个方法无论如何都会立即返回,获取不到锁时不会一直等待。
154+
155+ ` tryLock(long time, TimeUnit unit) ` 方法和 ` tryLock() ` 方法是类似的,区别仅在于这个方法在获取不到锁时会等待一定的时间,在时间期限之内如果还获取不到锁,就返回 false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回 true。
156+
157+ ` lockInterruptibly() ` 方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过 ` lock.lockInterruptibly() ` 想获取某个锁时,假若此时线程 A 获取到了锁,而线程 B 只有在等待,那么对线程 B 调用 ` threadB.interrupt() ` 方法能够中断线程 B 的等待过程。由于 ` lockInterruptibly() ` 的声明中抛出了异常,所以 ` lock.lockInterruptibly() ` 必须放在 try 块中或者在调用 ` lockInterruptibly() ` 的方法外声明抛出 ` InterruptedException ` 。
158+
159+ > 注意:当一个线程获取了锁之后,是不会被 interrupt() 方法中断的。因为本身在前面的文章中讲过单独调用 interrupt() 方法不能中断正在运行过程中的线程,只能中断阻塞过程中的线程。因此当通过 lockInterruptibly() 方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以响应中断的。
160+
161+ ` unlock() ` 方法的作用是释放锁。
162+
163+ ReentrantLock 是唯一实现了 Lock 接口的类。
149164
150165ReentrantLock 字面意为可重入锁。
151166
152167### 源码
153168
154- #### Lock
169+ #### Lock 接口定义
155170
156171``` java
157172public interface Lock {
158- /* * 获取锁,如果锁已被其他线程获取,则进行等待。 */
159173 void lock ();
160- /**
161- * 获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。
162- * 当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,
163- * 而线程B只有在等待,那么对线程B调用threadB.interrupt()* 方法能够中断线程B的等待过程。
164- */
165174 void lockInterruptibly () throws InterruptedException ;
166- /**
167- * tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回 true。
168- * 如果获取失败(即锁已被其他线程获取),则返回 false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
169- */
170175 boolean tryLock ();
171- /**
172- * 这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。
173- * 如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
174- */
175176 boolean tryLock (long time , TimeUnit unit ) throws InterruptedException ;
176- /* * 释放锁 */
177177 void unlock ();
178- /**
179- * 返回绑定到此Lock实例的新的Condition实例。
180- * 在等待条件之前,锁必须由当前线程保持。对 Condition.await 的调用将在等待之前以原子方式释放锁,
181- * 并在等待返回之前重新获取锁。
182- */
183178 Condition newCondition ();
184179}
185180```
186181
187- #### ReentrantLock
188-
189- ##### Sync
182+ #### ReentrantLock 属性和方法
190183
191- * ` Sync ` 这个类是 ` ReentrantLock ` 的同步控制核心。使用 AQS 状态来表示锁的保留数。
192- * ` Sync ` 是一个抽象类,有两个子类:
193- * ` FairSync ` - 公平锁版本。
194- * ` NonfairSync ` - 非公平锁版本。
184+ ReentrantLock 的核心方法当然是 Lock 中的方法(具体实现完全基于 ` Sync ` 类中提供的方法)。
195185
196- ##### 重要属性
197-
198- ` Sync ` 的实例。
186+ 此外,ReentrantLock 有两个构造方法,功能参考下面源码片段中的注释。
199187
200188``` java
189+ // 同步机制完全依赖于此
201190private final Sync sync;
202- ```
203-
204- ##### 重要方法
205-
206- ** 构造方法**
207-
208- ``` java
209- // 默认初始化一个非公平的重入锁
191+ // 默认初始化 sync 的实例为非公平锁(NonfairSync)
210192public ReentrantLock() {}
211- // 根据 boolean 值选择初始化一个公平的或不公平的重入锁
193+ // 根据 boolean 值选择初始化 sync 的实例为公平的锁(FairSync)或不公平锁(NonfairSync)
212194public ReentrantLock(boolean fair) {}
213195```
214196
215- ** 实现 Lock 接口的方法 **
197+ #### Sync
216198
217- 以下方法的功能可以参考 [ Lock] ( #lock-接口 ) 中的描述。具体实现完全基于 ` Sync ` 类中提供的方法。
199+ * ` Sync ` 类是 ` ReentrantLock ` 的内部类,也是一个抽象类。
200+ * ` ReentrantLock ` 的同步机制几乎完全依赖于` Sync ` 。使用 AQS 状态来表示锁的保留数(详细介绍参见 [ AQS] ( #aqs ) )。
201+ * ` Sync ` 是一个抽象类,有两个子类:
202+ * ` FairSync ` - 公平锁版本。
203+ * ` NonfairSync ` - 非公平锁版本。
218204
219- ``` java
220- void lock();
221- void lockInterruptibly() throws InterruptedException ;
222- boolean tryLock();
223- boolean tryLock(long time, TimeUnit unit) throws InterruptedException ;
224- void unlock();
225- Condition newCondition();
226- ```
205+ <p align =" center " >
206+ <img src =" https://raw.githubusercontent.com/dunwu/javase-notes/master/images/concurrent/ReentrantLock-diagram.png " >
207+ </p >
227208
228209### 示例
229210
@@ -256,31 +237,29 @@ public class ReentrantLockDemo {
256237}
257238```
258239
240+ :point_right : [ 更多示例] ( https://github.com/dunwu/javase-notes/tree/master/codes/concurrent/src/main/java/io/github/dunwu/javase/concurrent/lock )
241+
259242## ReadWriteLock 和 ReentrantReadWriteLock
260243
261244### 要点
262245
263- 作用
264-
265246对于特定的资源,ReadWriteLock 允许多个线程同时对其执行读操作,但是只允许一个线程对其执行写操作。
266247
267- ReentrantReadWriteLock 实现了 ReadWriteLock 接口,所以它是一个读写锁 。
248+ ReadWriteLock 维护一对相关的锁。一个是读锁;一个是写锁。将读写锁分开,有利于提高并发效率 。
268249
269- 原理
250+ ReentrantReadWriteLock 实现了 ReadWriteLock 接口,所以它是一个读写锁。
270251
271252“读-读”线程之间不存在互斥关系。
272253
273254“读-写”线程、“写-写”线程之间存在互斥关系。
274255
275- ReadWriteLock 维护一对相关的锁。一个是读锁;一个是写锁。将读写锁分开,有利于提高并发效率。
276-
277256<p align =" center " >
278257 <img src =" https://raw.githubusercontent.com/dunwu/javase-notes/master/images/concurrent/ReadWriteLock.jpg " >
279258</p >
280259
281260### 源码
282261
283- #### ReadWriteLock
262+ #### ReadWriteLock 接口定义
284263
285264``` java
286265public interface ReadWriteLock {
@@ -298,7 +277,7 @@ public interface ReadWriteLock {
298277
299278### 示例
300279
301- ```
280+ ``` java
302281public class ReentrantReadWriteLockDemo {
303282
304283 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock ();
0 commit comments