加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

ReentrantLock

发布时间:2020-12-15 05:25:40 所属栏目:Java 来源:网络整理
导读:参考:https://www.cnblogs.com/takumicx/p/9338983.html ReentrantLock可重入锁:jdk中独占锁的实现除了使用关键字 synchronized 外,还可以使用 ReentrantLock 。虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而

参考: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() + "t" + 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() + "t" + 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对象(公平锁与非公平锁: )

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是独占锁,当然需要一个属性来记录获取该锁的线程

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读