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秒
    ReentrantLock 基础方法使用及示例_第1张图片
    再次执行后还是会在每次自增后间隔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秒
ReentrantLock 基础方法使用及示例_第2张图片
执行结果:(可以多执行几遍观察一下)

线程名: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未获取到锁,不执行自增!

你可能感兴趣的:(学习拓展,java,开发语言)