参考:https://blog.csdn.net/qq_38293564/article/details/80515718
https://segmentfault.com/a/1190000014419022?utm_source=index-hottest
1.ReentrantLock分为公平锁和非公平锁,默认是不公平锁。(为什么默认是不公平锁呢?因为不公平锁线程切换少,吞吐率会更高,但是不公平锁容易造成“饥饿”)
公平锁就和syncnized差不多,先到先得,
非公平锁,就是ReentrantLock可重入的意思。就是当你当前的线程,或者你当前线程的子线程可以优先于其他的排队的线程获取到锁。
举个例子,有一个房间,房间里面有一个宝箱,拥有ReentrantLock的人可以打开宝箱。公平锁就是,只要你放下了ReentrantLock,就算你还没有出房子,你想再拿起ReentrantLock的时候去开宝箱的时候,也必须要出去拍到队尾去等着。非公平锁就是,只要你还没出房子,你就可以再拿起ReentrantLock去再开宝箱。这个例子里面房间等于线程,开宝箱是你线程里要做的事,拥有ReentrantLock和放下ReentrantLock就是lock()和unlock().
根据我参考的那个文章,自己差不多的写了的例子
package com.xq.demo.reentrantLock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.ReentrantLock;
public class MyFairAndUnfairTest {
private static class MyReentrantLock extends ReentrantLock {
public MyReentrantLock(boolean fair) {
super(fair);
}
public Collection<Thread> getQueuedThreads() {
List<Thread> arrayList = new ArrayList<Thread>(super.getQueuedThreads());
Collections.reverse(arrayList);
return arrayList;
}
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
//MyReentrantLock myReentrantLock = new MyReentrantLock(true);
MyReentrantLock myReentrantLock = new MyReentrantLock(false);
for(int i=0;i<10;i++){
Worder worder = new Worder(myReentrantLock,cyclicBarrier);
worder.setName(i+"");
worder.start();
}
}
static class Worder extends Thread{
private MyReentrantLock myReentrantLock;
private CyclicBarrier cyclicBarrier;
public Worder(MyReentrantLock myReentrantLock,CyclicBarrier cyclicBarrier){
this.myReentrantLock=myReentrantLock;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run(){
System.out.println(getName()+"准备好了");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
for(int i=0;i<2;i++){
myReentrantLock.lock();
System.out.println("当前占有锁的线程是:"+getName()+",等待获取锁的队列:"+myReentrantLock.getQueuedThreads());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myReentrantLock.unlock();
}
}
public String toString() {
return getName();
}
}
}
我们来分析代码运行的结果
首先是
MyReentrantLock myReentrantLock = new MyReentrantLock(false); 非公平锁,以下图片可以观察到,当线程9获取到锁,又释放锁,线程还没结束for循环再次获取锁的时候9又先于其他的等待线程着获取到了锁。
MyReentrantLock myReentrantLock = new MyReentrantLock(true);公平锁,下图结果可以看出,当线程9获取到锁,又释放锁,线程还没结束for循环再次获取锁的时候9被排到了等待锁的队尾去了。然后直到它前面排队的都走完,才轮到它。其他线程也一样。