锁-ReentrantLock解析

1.ReentrantLock和Synchronize的比较

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

公平锁:当锁可用时,在锁上等待的时间最长的线程将获得锁的使用权(讲究先到先得)。先被cpu时间片选中的线程先获得锁。大部分情况我们使用非公平锁,非公平锁的性能比公平锁的性能高,但是公平锁能够防止线程饥饿,某些情况会比较有用。

非公平锁:通过线程间的竞争获取锁的使用权。

ReentrantLock可响应中断:在死锁情况下,使用Synchronized会一直等待获取锁,造成程序无法继续运行。ReentrantLock获取锁时可以使用lockInterruptibly()方法,此方法线程可被外部中断,不必一直等待获取锁,解决死锁问题。

获取锁时限时等待:tryLock(time)指定时间内获取锁对象,成功返回true,失败返回false。

相同点:独占锁(同步)、可重入

不同点:ReentrantLock可以通过构造器实现公平锁和非公平锁。ReentrantLock可响应中断。ReentrantLock可限时获取锁对象。

2.同步方法:

调用lock.lock()方法的线程等价于获取了对象锁标记(对象监视器)。lock.unlock()释放锁对象。

3.Condition实现等待通知机制:

lock.newCondition()获取condition对象,并且一个lock对象可以创建多个Condition对象。在调用await()或signal()方法前需要先获取锁对象(lock.lock()),否则会抛出异常。并且线程的等待和通知需要针对于同一个condition。

object的wait()方法相当于condition中await();object的notify()方法相当于condition中的signal();object的notifyAll()方法相当于condition中的signalAll()。

注意:

当调用condition.await()方法时,线程自动释放掉当前持有的锁对象。当线程被唤醒时会自动获取到原有的锁对象。

关于condition的使用,可以参考经典案例:ArrayBlockingQueue

4.lock和unlock的实现逻辑

https://cloud.tencent.com/developer/article/1038499

CAS简述:

CAS(Compare And Swap),即比较并交换。它是一种乐观锁(synchronized可以看做是悲观锁)是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。

在JAVA中,sun.misc.Unsafe 类提供了硬件级别的原子操作来实现这个CAS。 java.util.concurrent 包下的大量类都使用了这个 Unsafe.java 类的CAS操作。

AQS简述:

AbstractQueuedSynchronizer 的缩写。AQS是一个用于构建锁和同步容器的框架。事实上concurrent包内许多类都是基于AQS构建,例如ReentrantLock,Semaphore,CountDownLatch,ReentrantReadWriteLock,FutureTask等。AQS解决了在实现同步容器时设计的大量细节问题。

AQS使用一个FIFO的队列表示排队等待锁的线程,队列中的每个节点都是双向链表的一环(有prev,next),头节点head不与任何节点关联,其他的节点都与等待线程关联,每个节点维护一个等待状态waitStatus。0表示正常状态,-1表示通知状态,表示该线程释放锁之后需要唤醒(通知)他的后继节点(儿子节点)。每当有一个新的线程newThread排进队列时,该节点newNode(newThread)自动成为尾部节点(tail)。如下是ReentrantLock的结构图:

AQS中的先进先出队列

AbstractQueuedSynchronizer中的lock方法

AbstractQueuedSynchronizer中的acquire方法

非公平锁获取锁对象nonfairTryAcquire

公平锁获取锁对象tryAcquire

添加等待队列节点addWaiter

挂起线程操作acquireQueued

锁的释放unlock

尝试释放锁对象tryRelease

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值