ReentrantLock实现公平锁和几个常用方法

培训教学 潘老师 6个月前 (11-10) 119 ℃ (0) 扫码查看

前文我们主要讲解了《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实现公平锁和几个常用方法的全部内容。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/teach/10953.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】