JDK并发包中的ReentrantLock函数有什么作用

发布时间:2021-11-12 14:11:08 作者:iii
来源:亿速云 阅读:167

这篇文章主要讲解了“JDK并发包中的ReentrantLock函数有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JDK并发包中的ReentrantLock函数有什么作用”吧!

显式锁-Lock与ReadWriteLock

JDK针对Lock的主要实现是ReentrantLock,ReadWriteLock实现是ReentrantReadWriteLock。

ReentrantReadWriteLock

两把锁共享一个等待队列,两把锁的状态都由一个原子变量表示,特有的获取锁和释放锁逻辑。

ReentrantReadWriteLock的基本原理:

ReentrantLock

主要方法

注: 这里的响应中断意思是若被其他线程中断(调用interrupt方法)会抛出InterruptedException异常。

原理支持

  1. 依赖CAS方法,可重入实现用的计数就是用的原子变量。

  2. 依赖LockSupport中的方法:

实现基础AQS

AQS-AbstractQueuedSynchronizer(抽象队列同步器)。

ReadWriteLock在内部注入了AbstractQueuedSynchronizer,上锁和释放锁核心方法都在AQS类当中,AQS维护了两个核心变量,一个是state(当前可重入计数,初始值为0),一个是exclusiveOwnerThread(当前持有锁的线程Thread对象)。另外还维护了一个锁等待队列。

ReentrantLock构造方法传入的boolean值ture为公平锁,false为不公平锁。以不公平锁为例先讲一下上锁和释放锁的原理:

上锁
  1. 如果当前锁状态为0(未被锁),则使用CAS获得锁,并设置当前锁内的线程为自己。

  2. 如果不为0,且持有锁的线程不是自己,则添加到队列尾部,并调用LockSupport中的park()方法放弃CPU执行权。直到当锁被释放的时候被唤醒,被唤醒后检查自己是否是第一个等待的线程,如果是且能获得锁,则返回,否则继续等待,这个过程中如果发生了中断,lock会记录中断标志位,但不会提前返回或抛出异常。

  3. 如果不为0,但持有锁线程是自己,则直接将state加1。

释放锁

就是将AQS内的state变量的值递减1,如果state值为0,则彻底释放锁,会将“加锁线程”变量也设置为null,同时唤醒等待队列中的第一个线程。

公平锁

为什么说上面的是不公平锁,释放锁时不是唤醒队列中第一个线程吗?为什么还会出现不公平的情况了,原因在于如果刚好释放锁,此时有一个线程进来尝试获取锁,可能会存在插队的情况。

公平锁原理

构造方法bollean传入true则代表的是公平锁,在获取锁方法中多了一个检查,意义是只有不存在其他等待时间更长的线程,它才会尝试获取锁。对比不公平锁,其整体性能比较低,低的原因不是这个检查慢,而是会让活跃线程得不到锁,进入等待状态,引起上下文切换,降低了整体的效率,

与synchrnized的区别

建议: synchronized以前的效率不如显式锁,但现在的版本两者效率上几乎没有区别,所以建议能用synchronized就用synchronized,需要实现synchronized办不到的需求如以上区别时,再考虑ReentrantLock。

显示条件

什么是显示条件

与wait和notify对应,用于线程协作,通过Lock的Condition newCondition()方法创建对应显示锁的显示条件;

方法

主要方法是await()和signal(),await()对应于Object的wait(),signal()对应于notify,signalAll()对应于notifyAll()

用法示例

public class WaitThread extends Thread {
    private volatile boolean fire = false;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    @Override
    public void run() {
        try {
            lock.lock();
            try {
                while (!fire) {
                    condition.await();
                }
            } finally {
                lock.unlock();
            }
            System.out.println("fired");
        } catch (InterruptedException e) {
            Thread.interrupted();
        }
    }

    public void fire() {
        lock.lock();
        try {
            this.fire = true;
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        WaitThread waitThread = new WaitThread();
        waitThread.start();
        Thread.sleep(1000);
        System.out.println("fire");
        waitThread.fire();
    }
}

当主线程调用fire方法时,子线程才被唤醒继续执行。

感谢各位的阅读,以上就是“JDK并发包中的ReentrantLock函数有什么作用”的内容了,经过本文的学习后,相信大家对JDK并发包中的ReentrantLock函数有什么作用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. ReentrantLock源码分析--jdk1.8
  2. java开发包jdk是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jdk reentrantlock

上一篇:Dimensions有什么作用

下一篇:Django中的unittest应用是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》