行业资讯 2025年08月6日
0 收藏 0 点赞 757 浏览 2335 个字
摘要 :

文章目录 公平锁与非公平锁 ReentrantLock实现公平锁 ReentrantLock的几个常用的方法 总结 前文我们主要讲解了《Java多线程:Lock显示锁详解》,其中重点讲解了Reentra……




前文我们主要讲解了《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.zuozi.net/9703.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号