ReentrantLock是一个可重入的互斥锁,也就是说该锁在某一时刻只能被同一个线程所持有一次或者多次,通过调整构造参数可以实现公平锁和非公平锁。
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock有一个带参的构造方法,通过传入true/false,可以实现公平锁和非公平锁,两者在获取锁时的策略有所不同。
当调用ReentrantLock的lock方法时,会根据公平或非公平调用具体同步器的tryAcquire方法,公平锁同步器FairSync.tryAcquire实现如下:
1protected final boolean tryAcquire(int acquires) {
2 final Thread current = Thread.currentThread();
3 int c = getState();
4 if (c == 0) {
5 //当前锁没有被其它线程持有,先判断队列中是否有线程在等待,没有的话才尝试获取锁
6 if (!hasQueuedPredecessors() &&
7 compareAndSetState(0, acquires)) {
8 setExclusiveOwnerThread(current);
9 return true;
10 }
11 }
12 else if (current == getExclusiveOwnerThread()) {
13 int nextc = c + acquires;
14 if (nextc < 0)
15 throw new Error("Maximum lock count exceeded");
16 setState(nextc);
17 return true;
18 }
19 return false;
20}
FairSync.tryAcquire源码参考:ReentrantLock.java
注释非公平锁同步器NonfairSync.tryAcquire实现如下:
1protected final boolean tryAcquire(int acquires) {
2 return nonfairTryAcquire(acquires);
3}
4
5final boolean nonfairTryAcquire(int acquires) {
6 final Thread current = Thread.currentThread();
7 int c = getState();
8 if (c == 0) {
9 //当前锁没有被其它线程持有,不判断队列中是否有线程在等待,直接尝试获取锁
10 if (compareAndSetState(0, acquires)) {
11 setExclusiveOwnerThread(current);
12 return true;
13 }
14 }
15 else if (current == getExclusiveOwnerThread()) {
16 int nextc = c + acquires;
17 if (nextc < 0) // overflow
18 throw new Error("Maximum lock count exceeded");
19 setState(nextc);
20 return true;
21 }
22 return false;
23}
NonfairSync.tryAcquire源码参考:ReentrantLock.java
注释1、通过使用ReentrantLock,修改main方法实现多线程顺序打印。
1public static void main(String[] args) throws Exception {
2 for (int i = 0; i < 10; i++) {
3 int num = i;
4 new Thread(() -> {
5 printNumber(num);
6 }).start();
7 }
8}
9
10private static void printNumber(int num) {
11 System.out.println(num);
12}
2、通过使用ReentrantLock,修改完善下面代码实现生产者消费者模型。
1import java.util.ArrayDeque;
2import java.util.Queue;
3
4public class Main {
5
6 private static final Queue<Object> queue = new ArrayDeque<>();
7 private static final int MAX_SIZE = 5;
8
9 public static void main(String[] args) {
10 for (int i = 0; i < 5; i++) {
11 new Thread(new Producer()).start();
12 }
13 for (int i = 0; i < 5; i++) {
14 new Thread(new Consumer()).start();
15 }
16 }
17
18 /**
19 * 生产者
20 */
21 static class Producer implements Runnable {
22
23 @Override
24 public void run() {
25
26 }
27 }
28
29 /**
30 * 消费者
31 */
32 static class Consumer implements Runnable {
33
34 @Override
35 public void run() {
36
37 }
38 }
39}