ReentrantLock源码分析

重入锁是java级别的锁。查看重入锁源码还是应该先阅读AbstractQueuedSynchronizer源码。

AbstractQueuedSynchronizer解析(1)
AbstractQueuedSynchronizer解析(2)

ReentrantLock类概述

  互斥的重入锁,与sychronized拥有相同的行为,但是它也有扩展的功能。最后一个持有锁的线程拥有重入锁。线程通过调用lock方法获取重入锁。如果当前线程已经持有锁将立刻返回。可以通过调用isHeldByCurrentThread方法检查锁是否被占有。

  这个类的构造器允许传入fairness参数。设置这个参数为true的时候,等待锁时间最长的线程将得到获取锁的权利。否则不会保证特定的获取锁的顺序。公平锁的性能会稍微低一点,但是它会保证每个线程都不会处于饥饿现象。机制一点,公平锁平不能保证线程按照计划的顺序执行。

  重入锁最多可以被同一个线程2147483647递归持有(每次持有锁都不释放锁)

非公平锁获取锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

static final class NonfairSync extends Sync {

final void lock() {

  //直接获取锁,不进行排队
if (compareAndSetState(0, 1))

setExclusiveOwnerThread(Thread.currentThread());

else //失败之后再次获取锁

acquire(1);

}

protected final boolean tryAcquire(int acquires) {

return nonfairTryAcquire(acquires);

}

}

非公平锁tryAcquire的业务逻辑由nonfairTryAcquire实现

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


final boolean nonfairTryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

 //锁未被任何线程占据
if (c == 0) {

if (compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

} //锁之前被当前线程占据,设置state为锁被当前线程重入次数
  //没有使用原子操作,没有同步,因为保证对state的操作只有一个线程
  //而且state被volatile修饰,内存可见性一定能保证
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;

}

公平锁获取锁

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

static final class FairSync extends Sync {

final void lock() {

acquire(1);

}

 // 等待队列为空即可获得锁,否则加入等待队列
protected final boolean tryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (!hasQueuedPredecessors() &&

compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

}//锁之前被当前线程占据,设置state为锁被当前线程重入次数
else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0)

throw new Error("Maximum lock count exceeded");

setState(nextc);

return true;

}

return false;

}

释放锁

只有持有锁的线程才能释放锁,改变state字段。

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

protected final boolean tryRelease(int releases) {

int c = getState() - releases;

  //必须持有锁才能释放
if (Thread.currentThread() != getExclusiveOwnerThread())

throw new IllegalMonitorStateException();

boolean free = false;

if (c == 0) {

free = true;

setExclusiveOwnerThread(null);

}

  //只有持有锁的线程才能改变state字段,不能担心线程安全
setState(c);

return free;

}