ReentrantLock 基础方法使用及示例

实现一个简单的线程安全的数字自增方法

public class CountNumImpl {
    //定义 ReentrantLock 锁
    private static ReentrantLock reentrantLock = new ReentrantLock();

    //自增数
    private static int num = 0;

    /**
     * 使用lock 的自增方法
     */
    public static void autoCountNum() {
        //获得锁(加锁)
        reentrantLock.lock();
        try {
            //执行业务方法 todo
            num++;
            System.out.println("线程名:"+Thread.currentThread().getName()+";当前数为:"+ num);
        }finally {
            //finally 块内总是 释放掉锁
            reentrantLock.unlock();
        }
    }


    //main 方法执行
    public static void main(String[] args) {
        //通过循环创建 10个线程,一起去调用 自增方法
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    autoCountNum();
                }
            }).start();
        }
    }
    
}

执行结果:

线程名:Thread-1获取到锁执行自增,当前数为:1
线程名:Thread-2获取到锁执行自增,当前数为:2
线程名:Thread-0获取到锁执行自增,当前数为:3
线程名:Thread-7获取到锁执行自增,当前数为:4
线程名:Thread-4获取到锁执行自增,当前数为:5
线程名:Thread-9获取到锁执行自增,当前数为:6
线程名:Thread-8获取到锁执行自增,当前数为:7
线程名:Thread-3获取到锁执行自增,当前数为:8
线程名:Thread-5获取到锁执行自增,当前数为:9
线程名:Thread-6获取到锁执行自增,当前数为:10

开始探索:

  • lock 方法:获取锁
    当Thread-1 在执行 lock 方法时未获得锁,则 Thread-1会一直阻塞直到获取锁;
    例如:在自增后设置线程休眠3秒
    在这里插入图片描述
    再次执行后还是会在每次自增后间隔3秒继续打印

  • tryLock 方法:尝试获取锁
    拿到锁后返回true,未拿到锁则直接返回false,不会进行阻塞/等待。(有参的 tryLock 方法可以设置等待/阻塞时间,即在等待时间内能拿到锁则返回 true,拿不到则返回false )

示例:无参的 unLock 方法

/**
     * 使用 unLock 的自增方法
     */
    public static void autoCountNumByUnlock() {
        //尝试获得锁(加锁)
        boolean b = reentrantLock.tryLock();
        if(!b){
            System.out.println("线程名:"+Thread.currentThread().getName()+"未获取到锁,不执行自增!");
            return;
        }

        try {
            //执行业务方法 todo
            num++;
            System.out.println("线程名:"+Thread.currentThread().getName()+"获取到锁执行自增,当前数为:"+ num);
        }finally {
            //finally 块内总是 释放掉锁
            reentrantLock.unlock();
        }
    }

执行结果:(可以多执行几遍观察一下)

线程名:Thread-1未获取到锁,不执行自增!
线程名:Thread-0获取到锁执行自增,当前数为:1
线程名:Thread-2未获取到锁,不执行自增!
线程名:Thread-3未获取到锁,不执行自增!
线程名:Thread-6未获取到锁,不执行自增!
线程名:Thread-4获取到锁执行自增,当前数为:2
线程名:Thread-5获取到锁执行自增,当前数为:3
线程名:Thread-7未获取到锁,不执行自增!
线程名:Thread-8获取到锁执行自增,当前数为:4
线程名:Thread-9获取到锁执行自增,当前数为:5

再在自增后设置线程休眠3秒
在这里插入图片描述
执行结果:(可以多执行几遍观察一下)

线程名:Thread-1未获取到锁,不执行自增!
线程名:Thread-3未获取到锁,不执行自增!
线程名:Thread-4未获取到锁,不执行自增!
线程名:Thread-2未获取到锁,不执行自增!
线程名:Thread-7未获取到锁,不执行自增!
线程名:Thread-0获取到锁执行自增,当前数为:1
线程名:Thread-8未获取到锁,不执行自增!
线程名:Thread-6未获取到锁,不执行自增!
线程名:Thread-5未获取到锁,不执行自增!
线程名:Thread-9未获取到锁,不执行自增!

示例:有参的tryLock

/**
     * 使用 unLock 的自增方法
     */
    public static void autoCountNumByUnlock() {
        //尝试获得锁(加锁)
        boolean b = false;
        try {
            //设置获得锁(自旋)的时间
            b = reentrantLock.tryLock(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        if(!b){
            System.out.println("线程名:"+Thread.currentThread().getName()+"未获取到锁,不执行自增!");
            return;
        }

        try {
            //执行业务方法 todo
            num++;
            System.out.println("线程名:"+Thread.currentThread().getName()+"获取到锁执行自增,当前数为:"+ num);
            //休眠3秒
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally {
            //finally 块内总是 释放掉锁
            reentrantLock.unlock();
        }
    }

执行结果:(可以多执行几遍观察一下)

线程名:Thread-0获取到锁执行自增,当前数为:1
线程名:Thread-2获取到锁执行自增,当前数为:2
线程名:Thread-3未获取到锁,不执行自增!
线程名:Thread-4未获取到锁,不执行自增!
线程名:Thread-5未获取到锁,不执行自增!
线程名:Thread-7未获取到锁,不执行自增!
线程名:Thread-6未获取到锁,不执行自增!
线程名:Thread-1未获取到锁,不执行自增!
线程名:Thread-8未获取到锁,不执行自增!
线程名:Thread-9未获取到锁,不执行自增!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值