从有点基础开始学JUC:Lock接口

105 阅读3分钟

Lock接口

Lock基本概念

Lock是 java.util.concurrent.locks 包 下的接口,Lock 实现提供了比 synchronized 关键字 更广泛的锁操作,它能以更优雅的方式处理线程同步问题。

Lock锁,可以得到和 synchronized一样的效果,即实现原子性、有序性和可见性。

相较于synchronized,Lock锁可手动获取锁和释放锁、可中断的获取锁、超时获取锁。

Lock 是一个接口,两个直接实现类:ReentrantLock(重入锁), ReentrantReadWriteLock(读写锁)。

1.Lock和ReadWriteLock是两大锁的根接口,Lock代表实现类是ReentrantLock(可重入锁),ReadWriteLock(读写锁)的代表实现类是ReentrantReadWriteLock。

  2.Lock 接口支持那些语义不同(重入、公平等)的锁规则,可以在非阻塞式结构的上下文(包括 hand-over-hand 和锁重排算法)中使用这些规则。

3.ReadWriteLock 接口以类似方式定义了一些读取者可以共享而写入者独占的锁。此包只提供了一个实现 ReentrantReadWriteLock。

4 .Lock是可重入锁,可中断锁,可以实现公平锁和读写锁,写锁为排它锁,读锁为共享锁。ReentrantLock也是一种排他锁

ReentrantLock

使用

创建一个锁

Lock l = new ReentrantLock();

建议使用:在将要加锁的逻辑代码放在try中,在finally中释放锁

l.lock();
try {
    ...
} finally {
    l.unlock();
}

方法

修饰符和类型方法描述
voidlockInterruptibly()获得锁,可中断。举个例子,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。
booleantryLock()锁在空闲的才能获取锁(未获得锁不会等待)。举个例子:当两个线程同时通过lock.trylock()想获取某个锁时,假若此时线程A获取到了锁,而线程B不会等待,直接放弃获取锁。
booleantryLock(long time, TimeUnit unit)如果锁定可用,则此方法立即返回值true。 如果锁不可用,则当前线程将被禁用以进行线程调度,并且在发生以下三种情况之一之前处于休眠状态: 当前线程获取锁。 其他一些线程中断当前线程。 等待时间过去了,返回false
voidunlock()释放锁。

ReadWriteLock

源码

public interface ReadWriteLock {
        
    // 读锁
    Lock readLock();
       
    // 写锁
    Lock writeLock();
}

eadWriteLock 接口的实现类 ReentrantReadWriteLock 读写锁提供了两个方法:readLock()和writeLock()用来获取读锁和写锁,也就是说将文件的读写操作分开,分成2个锁来分配给线程,从而使得多个线程可以同时进行读操作。

读写锁维护了两个锁,一个是读操作相关的锁也称为共享锁,一个是写操作相关的锁也称为排他锁。通过分离读锁和写锁,其并发性比一般排他锁有了很大提升。

多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥(只要出现写操作的过程就是互斥的)。在没有线程进行写操作时,进行读取操作的多个线程都可以获取读锁,而进行写入操作的线程只有在获取写锁后才能进行写操作。即多个线程可以同时进行读取操作,但是同一时刻只允许一个线程进行写入操作。

读锁和写锁

  • 多个线程可以同时获得读锁
  • 读锁可以共享,写锁只有在所有读锁释放后才能执行,但是当写锁在阻塞和获取过程中,之后的读锁也会阻塞,需要等到写锁释放后才能获取。

这就是这篇文章的内容了,欢迎大家的讨论,如有错漏,也请指出,谢谢~