ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JUC多线程:Lock锁介绍、ReentrantLock与synchronized的区别

2021-10-11 09:02:37  阅读:186  来源: 互联网

标签:JUC 释放 加锁 synchronized Lock ReentrantLock 线程 多线程


1、什么是 Lock 接口:

        JDK5 之后在 JUC 中加入了 Lock 接口,该接口中只有6个方法的声明。Lock 锁是显式锁,锁的持有与释放都必须手动编写,当前线程使用 lock() 方法与 unlock() 对临界区进行加锁与释放锁,当前线程获取到锁之后,其他线程由于无法持有锁将无法进入临界区,直到当前线程释放锁,unlock() 操作必须在 finally 代码块中,这样可以确保即使临界区执行抛出异常,线程最终也能正常释放锁。

2、什么是重入锁 ReentrantLock:

        ReentrantLock 重入锁是基于 AQS 框架并实现了 Lock 接口,支持一个线程对资源重复加锁,作用与 synchronized 锁机制相当,但比 synchronized 更加灵活,同时也支持公平锁和非公平锁。

对AQS抽象队列同步器原理感兴趣的读者可以阅读这篇文章:https://blog.csdn.net/a745233700/article/details/120668889

3、ReentrantLock 与 synchronized 的区别:

(1)使用的区别:synchronized 是 Java 的关键字,是隐式锁,依赖于 JVM 实现,当 synchronized 方法或者代码块执行完之后,JVM 会自动让线程释放对锁的占用;ReentrantLock 依赖于 API,是显式锁,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成。在发生异常时,JVM 会自动释放 synchronized 锁,因此不会导致死锁;而 ReentrantLock 在发生异常时,如果没有主动通过 unLock() 去释放锁,则很可能造成死锁现象,这也是 unLock() 语句必须写在 finally 语句块的原因。

(2)功能的区别:ReentrantLock 相比于 synchronzied 更加灵活, 除了拥有 synchronzied 的所有功能外,还提供了其他特性:

  • ReentrantLock 可以实现公平锁,而 synchronized 不能保证公平性。

  • ReentrantLock 可以知道有没有成功获取锁(tryLock),而 synchronized 不支持该功能

  • ReentrantLock 可以让等待锁的线程响应中断,而使用 synchronized 时,等待的线程不能够响应中断,会一直等待下去;

  • ReentrantLock 可以基于 Condition 实现多条件的等待唤醒机制,而如果使用 synchronized,则只能有一个等待队列

(3)性能的区别:在 JDK6 以前,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时,此时 ReentrantLock 的性能要远远优于 synchronizsed。但是在 JDK6 及以后的版本,JVM 对 synchronized 进行了优化,所以两者的性能变得差不多了

        总的来说,synchronizsed 和 ReentrantLock 都是可重入锁,在使用选择上需要根据具体场景而定,大部分情况下依然建议使用 synchronized 关键字,原因之一是使用方便语义清晰,二是性能上虚拟机已为我们自动优化。如果确实需要使用到 ReentrantLock 提供的多样化特性时,我们可以选择ReentrantLock

“可重入锁”概念是:自己可以再次获取自己的内部锁。比如一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。

4、读写锁:ReadWriteLock:

        ReentrantLock 某些时候有局限,如果使用 ReentrantLock,主要是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但如果线程C在读数据、线程D也在读数据,由于读数据是不会改变数据内容的,所以就没有必要加锁,但如果使用了 ReentrantLock,那么还是加锁了,反而降低了程序的性能,因此诞生了读写锁 ReadWriteLock。ReadWriteLock 是一个接口,而 ReentrantReadWriteLock 是 ReadWriteLock 接口的具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和写之间才会互斥,提升了读写的性能。

标签:JUC,释放,加锁,synchronized,Lock,ReentrantLock,线程,多线程
来源: https://blog.csdn.net/a745233700/article/details/120674310

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有