ReentrantLock锁实现原理,那CAS是啥
时间: 2024-01-12 13:02:31 浏览: 26
ReentrantLock是一种可重入的独占锁,基于AQS(AbstractQueuedSynchronizer)实现。它通过维护一个同步队列和一个状态变量,来控制共享资源的访问。线程获取锁会进行CAS操作,尝试将状态变量由0改为1,若成功则表示获取锁,若失败则将线程加入同步队列。释放锁时,则将状态变量由1改为0,并唤醒同步队列中的下一个线程。
CAS(Compare-And-Swap)是一种无锁算法,用于解决并发环境下的数据共享问题。它的原理是通过比较内存中某个位置的值和给定的旧值,若相等则更新该位置的值为新值。CAS操作需要硬件的原子性支持,常常被用来实现锁、计数器等并发控制机制。
相关问题
ReentrantLock 的实现原理
ReentrantLock是Java中的一个可重入锁,它的实现原理主要基于AQS(AbstractQueuedSynchronizer)框架。AQS是一个用于构建锁和同步器的框架,ReentrantLock就是基于AQS实现的。
ReentrantLock内部维护了一个同步状态变量state,通过CAS(Compare and Swap)操作来实现对state的原子更新。当一个线程获取锁时,会尝试将state从0改为1,如果成功获取到锁,则state为1,表示锁被当前线程持有;如果state已经为1,则说明锁已经被其他线程持有,当前线程需要进入等待队列。
当一个线程释放锁时,会将state减1,如果state变为0,则表示当前线程已经完全释放了锁;如果state仍然大于0,则说明当前线程还持有锁,其他等待的线程可以尝试获取锁。
ReentrantLock还支持可重入性,即同一个线程可以多次获取同一个锁而不会造成死锁。ReentrantLock通过维护一个持有锁的线程和一个计数器来实现可重入性。当一个线程再次获取锁时,会判断当前线程是否已经持有锁,如果是,则将计数器加1;如果不是,则需要进入等待队列。
除了基本的加锁和释放锁操作外,ReentrantLock还提供了一些其他的功能,比如条件变量的支持,可以通过Condition对象实现线程间的等待和唤醒操作。
reentrantlock原理_重入锁:ReentrantLock 详解
重入锁(ReentrantLock)是一种独占锁,也就是说同一时间只能有一个线程持有该锁。与 synchronized 关键字不同的是,重入锁可以支持公平锁和非公平锁两种模式,而 synchronized 关键字只支持非公平锁。
重入锁的实现原理是基于 AQS(AbstractQueuedSynchronizer)框架,利用了 CAS(Compare And Swap)操作和 volatile 关键字。
重入锁的核心思想是“可重入性”,也就是说如果当前线程已经持有了该锁,那么它可以重复地获取该锁而不会被阻塞。在重入锁内部,使用了一个计数器来记录当前线程持有该锁的次数。每当该线程获取一次锁时,计数器就加 1,释放一次锁时,计数器就减 1,只有当计数器为 0 时,其他线程才有机会获取该锁。
重入锁的基本使用方法如下:
```java
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockTest {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " get lock");
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + " release lock");
}
}, "Thread-1").start();
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " get lock");
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + " release lock");
}
}, "Thread-2").start();
}
}
```
在上面的示例代码中,我们创建了两个线程,分别尝试获取重入锁。由于重入锁支持可重入性,因此第二个线程可以成功地获取到该锁,而不会被阻塞。当第一个线程释放锁后,第二个线程才会获取到锁并执行相应的操作。
需要注意的是,使用重入锁时一定要记得在 finally 块中释放锁,否则可能会导致死锁的问题。同时,在获取锁时也可以设置超时时间,避免由于获取锁失败而导致的线程阻塞问题。