多线程笔记(十二):可重入锁 ReentrantLock

概念

       可重入锁,指的是同一线程外层函数(方法)获得锁之后,内层函数(方法)仍然能获得该锁的代码,同一线程在外层方法获取锁的时候,再进入内层方法会自动获取锁。

       简言之:已经获得该锁的线程,可以重复再次进入被该锁锁定的代码块。

       ReentrantLock 能够代替 synchronized 关键字完成独占锁的功能,并且允许占有锁线程的重入,显示地调用lock()、unlock()方法使得代码更灵活,收缩性更好。

       注意:我们常用的 synchronized 也是典型的可重入锁!

                  可重入锁是独占锁!独占-----即同一时间只能有一个线程持有锁。

       还不理解……直接上 Demo

可重入锁Demo

  1.基于 ReentrantLock 实现

/**
 * TODO 可重入锁Demo
 *
 * @author liuzebiao
 * @Date 2019-12-25 15:11
 */
public class ReentrantLockDemo {

    Lock lock = new ReentrantLock();//默认为非公平锁,构造器无参/传false, 公平锁需要传 true

    /**
     * 吃饭
     */
    public void eat(){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+":开始吃饭");
            //进入另一个加锁方法
            sleep();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 睡觉
     */
    public void sleep(){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+":开始睡觉");
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockDemo demo = new ReentrantLockDemo();
        new Thread(()->{
            demo.eat();
        },"Mary").start();
        new Thread(()->{
            demo.eat();
        },"Lucy").start();
    }
}

测试结果:

    Mary:开始吃饭
    Mary:开始睡觉
    Lucy:开始吃饭
    Lucy:开始睡觉

  2.基于 synchronized 实现

/**
 * TODO 基于synchronized,可重入锁Demo
 *
 * @author liuzebiao
 * @Date 2019-12-25 15:11
 */
public class SynchronizedDemo {

    /**
     * 吃饭
     */
    public synchronized void eat(){
        System.out.println(Thread.currentThread().getName()+":开始吃饭");
        //进入另一个加锁方法
        sleep();
    }

    /**
     * 睡觉
     */
    public synchronized void sleep(){
        System.out.println(Thread.currentThread().getName()+":开始睡觉");
    }

    public static void main(String[] args) {
        SynchronizedDemo demo = new SynchronizedDemo();
        new Thread(()->{
            demo.eat();
        },"Mary").start();
        new Thread(()->{
            demo.eat();
        },"Lucy").start();
    }
}

测试结果:

    Mary:开始吃饭
    Mary:开始睡觉
    Lucy:开始吃饭
    Lucy:开始睡觉

^_^ 到这儿应该就理解了 可重入锁的概念了吧

可重入锁实现原理

       每一个锁关联一个owner 线程持有者 state 计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM 会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。(源码层面分析)


附:原理分析

      本文仅介绍如何使用,如需了解 ReentrantLock 原理(源码分析),请跳转了解:可重入锁 ReentrantLock 原理分析


可重入锁 ReentrantLock 的用法,介绍到此为止

如果本文对你有所帮助,那就给我点个赞呗 ^_^ 

End

发布了247 篇原创文章 · 获赞 44 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/lzb348110175/article/details/103700232