ReentrantLock实现公平锁和几个常用方法
前文我们主要讲解了《Java多线程:Lock显示锁详解》,其中重点讲解了ReentrantLock的相关API实现锁机制,本文重点讲解ReentrantLock如何实现公平锁以及它的其他几个常用方法。
公平锁与非公平锁
大多数情况下,锁是非公平的,也就是说,当好几个线程在申请锁A时,可能某几个线程申请成功的概率大于其他线程。
公平锁:会按照时间先后顺序分配锁,保证先到先得,不会让线程饥饿。
ReentrantLock实现公平锁
synchronized这个内部锁是非公平的,ReentrantLock默认实现也是非公平锁,但是ReentrantLock在定义时可以通过其构造方法让其变成公平锁,即:ReentrantLock(boolean fair)。
//公平锁 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
可传入一个boolean值,true时为公平锁,false时为非公平锁
如果是非公平锁,系统会倾向于让一个已经获得了锁的线程继续获得锁,因为这样比较高效;如果是公平锁,系统会选择等待时间最长的那个线程获得锁。公平锁需要维护一个有序队列,所以性能不高。如果不是特别的需求,一般不使用公平锁。
/** * 公平锁和非公平锁 */ public class Test01 { // private static ReentrantLock lock = new ReentrantLock(); //默认是非公平锁 private static ReentrantLock lock = new ReentrantLock(true); //定义成公平锁 public static void main(String[] args) { for(int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { while(true) { try { lock.lock(); System.out.println(Thread.currentThread().getName() + "获得了锁"); } finally { lock.unlock(); } } } }, "Thread" + i).start(); } } }
ReentrantLock的几个常用的方法
1、 getHoldCount():返回当前线程调用lock()方法的次数;
public class Test02 { private static ReentrantLock lock = new ReentrantLock(); public static void m1() { try { lock.lock(); System.out.println(Thread.currentThread().getName() + "持有了:" + lock.getHoldCount()); //引文ReentrantLock是可重入锁,所以可以继续在m2()方法中继续获得锁 m2(); } finally { lock.unlock(); } } public static void m2() { try { lock.lock(); System.out.println(Thread.currentThread().getName() + "持有了:" + lock.getHoldCount()); } finally { lock.unlock(); } } public static void main(String[] args) { m1(); } }
2、 getQueueLength():返回正等待获得此锁的线程预估数;
/** * getQueueLength() 返回获得锁的线程预估数 */ public class Test03 { private static ReentrantLock lock = new ReentrantLock(); private static class SubThread extends Thread { @Override public void run() { try { lock.lock(); TimeUnit.SECONDS.sleep(1); System.out.println(Thread.currentThread().getName() + ":" + lock.getQueueLength()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) { for(int i = 0; i < 10; i++) { new SubThread().start(); } } }
3、 getWaitQueueLength(Conditioncondition):返回在condition队列上等待的线程预估数;
4、 hasQueuedThread(Threadthread):查询某线程是否在等待获得该锁;
5、 hasQueuedThreads():查询是否有其他线程在等待获得该锁;
6、 hasWaiters(Conditioncondition):查询在该condition队列上是否有线程在等待;
7、 isHeldByCurrentThread():判断锁是否被当前线程锁持有;
8、 isLocked():判断锁是否被任何一个线程锁持有;
这里就不再使用代码演示了,有兴趣的可以自己去尝试下。
总结
以上就是ReentrantLock实现公平锁和几个常用方法的全部内容。