• ReentrantLock


    参考:https://www.cnblogs.com/takumicx/p/9338983.html

    ReentrantLock可重入锁:jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock。虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。

    • 1、ReentrantLock和synchronized都是独占锁,只允许线程互斥的访问临界区。但是实现上两者不同:synchronized加锁解锁的过程是隐式的,用户不用手动操作,优点是操作简单,但显得不够灵活。一般并发场景使用synchronized的就够了;ReentrantLock需要手动加锁和解锁,且解锁的操作尽量要放在finally代码块中,保证线程正确释放锁。ReentrantLock操作较为复杂,但是因为可以手动控制加锁和解锁过程,在复杂的并发场景中能派上用场。

    • 2、ReentrantLock和synchronized都是可重入的。synchronized因为可重入因此可以放在被递归执行的方法上,且不用担心线程最后能否正确释放锁;而ReentrantLock在重入时要却确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。

    不使用ReentrantLock锁的情况:

    // 不使用锁
    public
    class Demo09 implements Runnable { public static ReentrantLock lock = new ReentrantLock(); //锁 相当于一份公共资源 public static void main(String[] args) { Thread t1 = new Thread(new Demo09()); Thread t2 = new Thread(new Demo09()); t1.start(); t2.start(); } @Override public void run() { // lock.lock(); // 获取锁 for(int j = 0; j < 3; j++) { System.out.println(Thread.currentThread().getName() + " " + j); } // lock.unlock(); // 释放锁 } }

    结果:

    使用ReentrantLock:

    public class Demo09 implements Runnable {
        public static ReentrantLock lock = new ReentrantLock();  //锁  相当于一份公共资源
        public static void main(String[] args) {
            Thread t1 = new Thread(new Demo09());
            Thread t2 = new Thread(new Demo09());
            t1.start();
            t2.start();
        }
        @Override
        public void run() {
            lock.lock(); // 获取锁
            for(int j = 0; j < 3; j++) {
                System.out.println(Thread.currentThread().getName() + "	" + j);
            }
            lock.unlock(); // 释放锁
            
        }
    }

     结果:

    源码分析:

     首先看构造函数:

    /**
    * Creates an instance of {@code ReentrantLock}.
    * This is equivalent to using {@code ReentrantLock(false)}.
    */
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    
    /**
    * Creates an instance of {@code ReentrantLock} with the
    * given fairness policy.
    *
    * @param fair {@code true} if this lock should use a fair ordering policy
    */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    默认创建一个非公平锁,如果传入参数为true即创建一个公平锁,然后获取一个Sync对象(公平锁与非公平锁https://www.cnblogs.com/DDiamondd/p/11316393.html

    abstract static class Sync extends AbstractQueuedSynchronizer {}

     Sync类继承了AbstractQueuedSynchronizer (AQS 抽象队列同步器,定义了一套多线程访问共享资源的同步器框架)

     public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {}

     AbstractQueuedSynchronizer类里面有两个非常重要的参数:

    1)state:当前锁的状态,初始值为0。 当某个线程获取一次该锁state就+1, 释放一次该锁state就-1,也只有当state=0时,其他线程才有机会获取锁

    2)exclusiveOwnerThread: 获取锁的线程  这个属性是继承于 AbstractOwnableSynchronizer类,因为ReentrantLock是独占锁,当然需要一个属性来记录获取该锁的线程

  • 相关阅读:
    C++之栈的应用-------判断出栈序列是否合法
    PHP 使用soap调用webservice接口
    C++矩阵转置
    C++利用栈实现队列、利用队列实现栈
    C++ error LNK2019: 无法解析的外部符号
    定时任务
    spring boot redis CacheManager
    非正常关闭vim编辑器后提示错误的解决方法
    python pandas学习记录 二
    layui点击放大图片
  • 原文地址:https://www.cnblogs.com/DDiamondd/p/11315978.html
Copyright © 2020-2023  润新知