一、公平策略

在多个线程争用锁的情况下,公平策略倾向于将访问权授予等待时间最长的线程。也就是说,相当于有一个线程等待队列,先进入等待队列的线程后续会先获得锁,这样按照“先来后到”的原则,对于每一个等待线程都是公平的。

Java并发之ReentrantLock公平策略(二)_加锁

场景分析:

 1.持有锁的线程A正在running,对列中有线程BCDE被挂起并等待被唤醒;

 2.线程E执行lock,队列中有线程BCD在等待,线程E直接加入到队列的队尾。​

实践示例:

Java并发之ReentrantLock公平策略(二)_访问权_02

输出:

Java并发之ReentrantLock公平策略(二)_等待队列_03

我们一共定义了A、B、C、D、E共五个线程,在runThead()方法中循环执行3次加锁和解锁的过程。从多次执行的结果来看他们始终按照A-B-C-D-E的顺序输出。

二、非公平策略

在多个线程争用锁的情况下,能够最终获得锁的线程是随机的(由底层OS调度)。

Java并发之ReentrantLock公平策略(二)_访问权_04

场景分析:

1.线程A和B同时执行CAS指令,假设线程A成功,线程B失败,则表明线程A成功获取锁,并把同步器中的exclusiveOwnerThread设置为线程A。

2.竞争失败的线程B,在nonfairTryAcquire方法中,会再次尝试获取锁,也就是在这段时间如果线程A释放锁,线程B就可以直接获取锁而不用挂起。完整的执行流程如下:

Java并发之ReentrantLock公平策略(二)_访问权_05

实际示例:

Java并发之ReentrantLock公平策略(二)_加锁_06

输出:

Java并发之ReentrantLock公平策略(二)_访问权_07

我们同样定义了A、B、C、D、E共五个线程,在runThead()方法中循环执行3次加锁和解锁的过程。从多次执行的结果来看输出的顺序没有规律可言,完全是随机不可预知的。