前言:随着多线程程序的普及,线程同步的问题变得越来越常见。Java中提供了多种同步机制来确保线程安全,其中之一就是ReentrantLock。ReentrantLock是Java中比较常用的一种同步机制,它提供了一系列比synchronized更加灵活和可控的操作和特性。在本篇博客中,我们将深入探讨ReentrantLock的使用和原理,并与synchronized进行对比分析,让读者更好地理解和掌握线程同步机制的应用技巧。
🚀 作者简介:作为某云服务提供商的后端开发人员,我将在这里与大家简要分享一些实用的开发小技巧。在我的职业生涯中积累了丰富的经验,希望能通过这个博客与大家交流、学习和成长。技术栈:Java、PHP、Python、Vue、React
本文收录于三木的🎈 「Java探索者之路」系列专栏,这个专栏旨在引领Java开发者踏上一段真正探索Java世界的旅程。
我们将深入探讨Java编程的方方面面,从基础知识到高级技巧,从实践案例到最新趋势,帮助你成为一名卓越的Java探索者。如果有想进入Java后端领域工作的同学,这个专栏会对你有所帮助,欢迎关注起来呀
🔥「面试」这个专栏的灵感来自于许多粉丝私信,大家向我咨询有关面试的问题和建议。我深感荣幸和责任,希望通过这个专栏,能够为大家提供更多关于面试的知识、技巧和经验。我们将一起探讨面试。期待粉丝们ssp的offer喜讯。
🌼 本人也会持续的去关注AIGC以及人工智能领域的一些动向并总结到博客中,大家感兴趣的可以关注一下我的「AI」专栏
🌊 「Python爬虫」的入门学习系列,大家有兴趣的可以看一看
🌹一起学习,互三互访,顺评论区有访必回,有关必回!!!
正文
ReentrantReadLock
属于一种手动获取释放的可重入锁,也就是操作系统中用到的读锁,是Lock
的一种实现类。
Lock
接口的定义如下:
public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
lock/unlock
普通的获取锁和释放锁方法,会阻塞直到成功.tryLock
尝试获取锁,立即返回,不阻塞,如果获取成功,返回true
,否则返回false
。tryLock(long time, TimeUnit unit)
- 尝试获取锁,如果能成功则立即返回
true
,否则阻塞等待 - 但等待的最长时间由指定的参数设置,在等待的同时响应中断,如果发生了中断,抛出
InterruptedException
- 如果在等待的时间内获得了锁,返回
true
,否则返回false
。
Lock
接口的主要实现类是ReentrantLock
,它的基本用法lock/unlock
实现了与synchronized
一样的语义,包括:
- 可重入,一个线程在持有一个锁的前提下,可以继续获得该锁;
- 可以解决竞态条件问题;
- 可以保证内存可见性。
ReentrantLock
有两个构造方法:
public ReentrantLock() public ReentrantLock(boolean fair) // 参数fair表示是否保证公平,不指定的情况下,默认为false,表示不保证公平
所谓公平是指,等待时间最长的线程优先获得锁。保证公平会影响性能,一般也不需要,所以默认不保证,
synchronized
锁也是不保证公平的。
使用显式锁,一定要记得调用unlock
。一般而言,应该将lock之后的代码包装到try
语句内,在finally
语句内释放锁。
reentrantLock
与 synchrozined
的区别
相比synchronized
, ReentrantLock
可以实现与synchronized
相同的语义,而且支持以非阻塞方式获取锁,可以响应中断,可以限时,更为灵活。不过,synchronized
的使用更为简单,写的代码更少,也更不容易出错。
synchronized
代表一种声明式编程思维,程序员更多的是表达一种同步声明,由Java
系统负责具体实现,程序员不知道其实现细节;显式锁代表一种命令式编程思维,程序员实现所有细节。
声明式编程的好处除了简单,还在于性能,在较新版本的JVM
上,ReentrantLock
和synchronized
的性能是接近的,但Java
编译器和虚拟机可以不断优化synchronized
的实现,比如自动分析synchronized
的使用,对于没有锁竞争的场景,自动省略对锁获取/释放的调用。
简单总结下,能用synchronized
就用synchronized
,不满足要求时再考虑Reentrant-Lock
。