在Java中,ReentrantLock
是常用的锁机制,是一种可重入的互斥锁(Reentrant Mutual Exclusion Lock)。相对于synchronized
,它供给更多的灵活性、可扩展性和更高的并发性。
答复
-
ReentrantLock
内部运用了一个Sync
内部类完成了锁的基本功能。Sync
继承了AQS
类,经过对内部状况值的设置来确保互斥。
AbstractQueuedSynchronizer
是一个抽象类,它供给了一种多线程拜访共享资源的机制,适当于是为锁供给了一个通用的框架。
-
Sync
内部维护了一个state
属性,表明当时的资源状况。当state
为 0 时,表明资源未被占用;当 state 大于 0 时,表明资源已被占用。 - 调用
lock()
办法时,Sync
内部会经过compareAndSetState()
函数来测验获取锁。假如获取锁失败,会将当时线程加入到等候行列中,等候唤醒后再次测验获取锁。 - 调用
unlock()
办法时,会开释锁,并唤醒等候行列中的线程。 -
ReentrantLock
还完成了可重入特性。ReentrantLock 内部运用一个计数器来记载取得该锁的次数,每次unlock()
都会将计数器减一,只有计数器为 0 时才会真实开释锁。
AQS类
AQS
是Java中的一个同步东西,全称为AbstractQueuedSynchronizer
,它是Java并发包中其他同步东西的基础,例如ReentrantLock、CountDownLatch、Semaphore
等。
AQS
是一种完成线程同步的框架,它供给了一个行列,能够对这个行列中的元素进行加锁和开释锁的操作,以此来确保多个线程同步拜访某个资源时的安全性。
AQS
的基本思想是,经过一个抽象类来完成同步器,该同步器维护了一个FIFO
行列,对该行列中的每个元素进行加锁或解锁操作,从而完成多线程对共享资源的同步拜访。
经过继承AQS
类并完成它的抽象办法,能够完成多种锁和同步东西。AQS
的中心办法是acquire
和release
,它们定义了一种获取锁和开释锁的原子操作方法,具有较高的灵活性和扩展性。
ReentrantLock概述
ReentrantLock
是Java中一个可重入的互斥锁,被广泛应用于多线程并发操控场景。它答应线程在取得锁之后多次进入同一代码块,而不是简略的阻塞。ReentrantLock有一些特别的办法,如lock()和unlock(),使得它更灵活,更可控和更适合细粒度的操控。同时,它答应多个线程同时拜访锁,并具有公平和非公平锁两种机制,答应在竞争高的情况下提高并发性。
ReentrantLock底层完成
ReentrantLock
的底层完成根据AbstractQueuedSynchronizer
(AQS)。AQS是一个自旋锁的框架,供给多种锁的完成,如独占锁、共享锁等。AQS
的完成根据一种先进先出(FIFO)行列的方法,经过一个state变量来记载锁的状况,使其更高效。
ReentrantLock
是经过完成AQS
来完成锁的操作的。它根据AQS的独占锁机制,只答应一个线程取得锁。当一个线程获取了锁时,它就会将state
的值加1,假如这个线程再次请求这个锁时,它不需求再去获取锁,而是直接添加state
的值,并让线程进入等候状况,这个操作叫做重入。而这个线程开释锁时,则会将state
的值减1,当state
的值为0时,这个锁就能被其他的线程获取。
由于AQS
是根据类似于自旋锁的方法完成的,所以干等锁的线程是处于阻塞状况,而是处于循环等候的状况。这种方法能够避免线程进入睡觉状况以及线程上下文切换所带来的开支,使得锁的取得更快速,同时也减少了体系开支。