java.util.concurrent.locks.ReentrantReadWriteLock类

java.util.concurrent.locks.ReentrantReadWriteLock类


特点

  1. ReentrantReadWriteLock可重入锁 —— 线程可以获取已经获取了没有释放的锁ReentrantReadWriteLock最多支持65535个递归WRITE锁和65535个READ锁;

  2. ReentrantReadWriteLock的写锁是排他锁:在同一时刻只能有一个WRITE线程可以访问,WRITE锁获取成功后所有其他WRITE线程和READ线程都会被阻塞

    为了防止已经获取READ锁的线程无法感知WRITE线程的操作,只有全部READ锁释放时才允许获取READ锁

  3. ReentrantReadWriteLock的读锁是共享锁:在同一时刻允许有多个READ线程访问,只要没有WRITE线程

  4. ReentrantReadWriteLock继承自Lock接口,同时支持非公平锁和公平锁;

  5. 锁降级:WRITE锁可以降级为READ锁


成员变量

  1. private final ReentrantReadWriteLock.ReadLock readerLock;内部READ锁
  2. private final ReentrantReadWriteLock.WriteLock writerLock;内部WRITE锁
  3. final Sync sync;:内部类Sync的实例,通过AQS保证获取资源的线程安全性,是锁的实际实现

Sync内部通过一个32位的int变量维护读写锁的多种状态:高16位标识读,低16位表示写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//内部类Sync,继承自AQS
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;

//移位常量:16
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
//最大线程数量
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
//即0x0000FFFF
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

//读锁,共享锁,用一个int变量的高16位表示
static int sharedCount(int c) {
// c右移16位,求高16位
return c >>> SHARED_SHIFT;
}

//写锁,排他锁,用一个int变量的低16位表示
static int exclusiveCount(int c) {
// 相当于 c & 0x0000FFFF,求c的低16位
return c & EXCLUSIVE_MASK;
}

//尝试获取写锁
//@param: int acquires 尝试获取的线程数
protected final boolean tryAcquire(int acquires) {
//当前线程
Thread current = Thread.currentThread();
//获取当前可用锁个数
int c = getState();
//state低16位,写锁
int w = exclusiveCount(c);
if(c != 0) {
// c != 0 && w == 0,表示已经有写锁
//current != getExclusiveOwnerThread():
//当前线程不是已经获取了锁的线程,不涉及可重入
if(w == 0 || current != getExclusiveOwnerThrad()) {
return false;
}
//获取锁后超过最大线程数量
if(w + exclusiveCount(acquires) > MAX_COUNT){
throw new Error("Maximum lock count exceeded");
}
//成功获取锁
getState(c + acquires);
return true;
}
//如果写锁需要阻塞(只有读锁全部释放才允许获取写锁),
//或者CAS设置state变量失败
if(writerShouldBlock() || !compareAndSetState(c, c + acquires)) {
return false;
}
//将当前线程 设置为 获取排他写锁的线程
setExclusiveOwnerThread(current);
return true;
}




}

API

1. 构造函数

  1. public ReentrantReadWriteLock():默认构造函数,非公平锁
1
2
3
4
//默认构造函数,非公平锁
public ReentrantReadWriteLock() {
this(false); //调用boolean的构造函数
}
  1. public ReentrantReadWriteLock(boolean fair)传入公平性的构造函数:默认fair == false,非公平锁;fair == true,公平锁
1
2
3
4
5
6
//传入公平性的构造函数,默认非公平锁
public ReentrantReadWriteLock(boolean fair){
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}

2. 获取读锁:readLock()

  • public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
1
2
3
public static class ReadLock implements Lock, java.io.Serializable {
//...
}

3. 获取写锁:writeLock()

  • public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
  • 最终会调用内部类SynctryAcquire(int acquires)方法

4. 释放写锁:unlock()

1
2
3
4
5
6
public static class WriteLock implements Lock, java.io.Serializable {
//释放写锁,底层调用的是AQS的release(int arg)
public void unlock() {
sync.release(1);
}
}
1
2
3
4
5
6
7
8
9
10
11
//释放写锁
public final boolean release(int arg) {
if(tryRelease(arg)){
Node h = head;
if(h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
-------------本文结束感谢您的阅读-------------

本文标题:java.util.concurrent.locks.ReentrantReadWriteLock类

文章作者:DragonBaby308

发布时间:2019年09月18日 - 22:35

最后更新:2019年09月22日 - 10:09

原始链接:http://www.dragonbaby308.com/java-util-concurrent-locks-ReentrantReadWriteLock/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

急事可以使用右下角的DaoVoice,我绑定了微信会立即回复,否则还是推荐Valine留言喔( ఠൠఠ )ノ
0%