ReentrantLock类
Sychronized关键字可以来实现线程之间的同步,ReentrantLock类也可以达到同样的效果,并且在拓展功能上跟强大。
ReentrantLock的优势
ReentrantLock是一种可重入锁,它能进入已经加锁的同步代码块,不会出现阻塞自己的情况,相比Sychronized要等待到锁执行完毕,它可以中断响应,
锁类型
ReentrantLock是有两种锁的,一种是非公平锁,一种是公平锁(FairSync),默认是一种非公平锁(NonfairSync)。
1 | //默认构造是非公平锁 |
非公平锁1
2
3
4
5
6final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
非公平锁,不用等待队列中的其他线程,可以直接抢占尝试获取锁。compareAndSetState方法使用unsafe的CAS实现对状态的原子操作
公平锁1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19protected 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;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
判断AQS中c的状态,如果hasQueuedPredecessors为空和状态等于0,表示队列中没用线程,可以尝试获取锁,利用CSA更改状态,如果状态大于
0,说明锁被获取了,然后判断获取锁的线程是否为当前线程,是则需要将 state + 1,并将值更新。
原理
ReentrantLock构造新建Sync,而sync是继承AQS(AbstractQueuedSynchronizer)的,
1 | static final class NonfairSync extends Sync {} |
使用
Lock lock=new ReentrantLock();
调用ReentrantLock对象的lock()方法获取锁,调用unlock()方法释放锁。 调用lock.lock()的线程就持有了“对象监视器”。
1 |
|
结果: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
50ThreadName=Thread-1 1
ThreadName=Thread-1 2
ThreadName=Thread-1 3
ThreadName=Thread-1 4
ThreadName=Thread-1 5
ThreadName=Thread-1 6
ThreadName=Thread-1 7
ThreadName=Thread-1 8
ThreadName=Thread-1 9
ThreadName=Thread-1 10
ThreadName=Thread-0 1
ThreadName=Thread-0 2
ThreadName=Thread-0 3
ThreadName=Thread-0 4
ThreadName=Thread-0 5
ThreadName=Thread-0 6
ThreadName=Thread-0 7
ThreadName=Thread-0 8
ThreadName=Thread-0 9
ThreadName=Thread-0 10
ThreadName=Thread-2 1
ThreadName=Thread-2 2
ThreadName=Thread-2 3
ThreadName=Thread-2 4
ThreadName=Thread-2 5
ThreadName=Thread-2 6
ThreadName=Thread-2 7
ThreadName=Thread-2 8
ThreadName=Thread-2 9
ThreadName=Thread-2 10
ThreadName=Thread-3 1
ThreadName=Thread-3 2
ThreadName=Thread-3 3
ThreadName=Thread-3 4
ThreadName=Thread-3 5
ThreadName=Thread-3 6
ThreadName=Thread-3 7
ThreadName=Thread-3 8
ThreadName=Thread-3 9
ThreadName=Thread-3 10
ThreadName=Thread-4 1
ThreadName=Thread-4 2
ThreadName=Thread-4 3
ThreadName=Thread-4 4
ThreadName=Thread-4 5
ThreadName=Thread-4 6
ThreadName=Thread-4 7
ThreadName=Thread-4 8
ThreadName=Thread-4 9
ThreadName=Thread-4 10
由结果可知,实现了同步。
ReentrantReadWriteLock类
因为ReentrantLock.lock()方法后面的任务,这样虽然保证了实例变量的线程安全性,但是效率却是非常低下的。所有提供了一种读写锁ReentrantReadWriteLock类(也叫排他锁)
1 | public class Service { |
结果:1
2获取读锁A 1545462698121
获取写锁B 1545462699122