Java中的锁之Lock接口

本文介绍了Java中Lock接口。在Java SE 5之后,并发包新增Lock接口实现锁功能,它与synchronized类似,但有更多同步特性。阐述了锁的概念,对比了Lock与synchronized的区别,还说明了Lock锁的使用注意事项及相关API,最后列出了参考文献。

在这里插入图片描述

一.Lock接口简介

首先,我们一睹尊容:
在这里插入图片描述
在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。

1.什么是锁

锁是一个工具,用于控制多个线程对共享资源的访问。通常,锁提供对共享资源的独占访问:每次只有一个线程可以获得锁,而对共享资源的所有访问都要求先获得锁。但是,有些锁可能允许并发访问共享资源,比如{ReadWriteLock}的读锁。

2.锁和synchronized的区别

使用synchronized关键字将会隐式地获取锁,但是它将锁的获取和释放固化了,也就是先获取再释放。当然,这种方式简化了同步的管理,可是扩展性没有显示的锁获取和释放来的好。例如,针对一个场景,手把手进行锁获取和释放,先获得锁A,然后再获取锁B,当锁B获得后,释放锁A同时获取锁C,当锁C获得后,再释放B同时获取锁D,以此类推。这种场景下,synchronized关键字就不那么容易实现了,而使用Lock却容易许多。

二.Lock锁使用

Lock lock = new ReentrantLock();
lock.lock();
try {
} finally {
lock.unlock();
}

在finally块中释放锁,目的是保证在获取到锁之后,最终能够被释放。不要将获取锁的过程写在try块中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放。

三.Lock接口API

在这里插入图片描述

参考文献
1.Java并发编程艺术 [方腾飞 魏鹏 程晓明 著]

上一篇下一篇
返回专栏目录
<think>我们正在讨论Java中的Lock接口。用户之前询问了Lock的实现类,现在转向Lock接口本身定义的方法。Lock接口位于java.util.concurrent.locks包中,是Java并发编程中用于替代synchronized关键字的一种更灵活的机制。 根据Java文档,Lock接口定义了以下方法: 1. void lock():获取。如果不可用,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到获得。 2. void lockInterruptibly():获取,除非当前线程被中断。如果可用,则获取并立即返回。如果不可用,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到以下两种情况之一发生: - 被当前线程获取; - 其他某个线程中断当前线程。 3. boolean tryLock():仅在调用时为空闲状态才获取该。如果可用,则获取,并立即返回true。如果不可用,则立即返回false。 4. boolean tryLock(long time, TimeUnit unit):如果在给定的等待时间内空闲,并且当前线程未被中断,则获取。如果在给定时间内可用,并且当前线程未被中断,则获取并返回true;如果超过指定时间,则返回false;如果在等待过程中当前线程被中断,会抛出InterruptedException并清除中断状态。 5. void unlock():释放。注意,通常必须由持有它的线程释放,并且通常应该放在finally块中以确保释放。 6. Condition newCondition():返回绑定到此Lock实例的新Condition实例。Condition提供了类似于Object.wait()/notify()的线程等待/唤醒机制,但更灵活,支持多个等待集。 注意:Lock接口的实现类必须提供与隐式监视器(synchronized)相同的内存同步语义,但可以有不同的行为(如重入性、公平性等)。 现在,我们根据用户提供的引用,虽然这些引用主要涉及synchronized、并发队列和注解,但我们可以忽略不相关的引用,专注于Lock接口的方法。 回答结构: 1. 首先列出Lock接口的所有方法,并简要说明每个方法的作用和注意事项。 2. 给出一个简单的使用示例,展示Lock的基本用法(lock()和unlock())。 3. 可以提一下Condition的使用,因为它是Lock接口提供的一个重要特性。 最后,生成相关问题,引导用户深入了解Lock的使用和高级特性。 注意:用户引用中提到了ConcurrentLinkedDeque等无队列,但这里我们关注的是Lock接口,所以不展开无算法。 示例代码: 我们将展示一个使用ReentrantLockLock的一个实现)的简单示例,包括tryLock和Condition的使用(可选)。 由于用户要求生成相关问题,我们在最后提出几个相关问题。</think>### Java中`Lock`接口定义的方法详解 `Lock`接口是`java.util.concurrent.locks`包的核心,提供了比`synchronized`更灵活的控制机制。以下是其定义的全部方法: #### 核心方法 1. **`void lock()`** - 获取(阻塞直到获得) - **示例**: ```java lock.lock(); try { // 临界区代码 } finally { lock.unlock(); // 必须在finally块释放[^3] } ``` 2. **`void unlock()`** - 释放(**必须显式调用**,否则导致死) - 只能由持有的线程调用 3. **`boolean tryLock()`** - 非阻塞尝试获取 - 成功返回`true`,失败立即返回`false` - **示例**: ```java if (lock.tryLock()) { try { /* 操作资源 */ } finally { lock.unlock(); } } else { // 执行备用逻辑 } ``` 4. **`boolean tryLock(long time, TimeUnit unit)`** - 带超时的尝试获取 - 在指定时间内等待可用 - **示例**: ```java if (lock.tryLock(2, TimeUnit.SECONDS)) { // ... } ``` 5. **`void lockInterruptibly()`** - 可中断的获取(响应线程中断) - 若等待中被中断,抛出`InterruptedException` - **示例**: ```java try { lock.lockInterruptibly(); // ... } catch (InterruptedException e) { // 处理中断 } ``` 6. **`Condition newCondition()`** - 创建绑定到当前的`Condition`对象 - 用于实现线程等待/通知机制(类似`wait()/notify()`) - **示例**: ```java Condition cond = lock.newCondition(); cond.await(); // 等待 cond.signal(); // 唤醒 ``` --- ### 关键特性总结 | 方法 | 阻塞性 | 响应中断 | 超时支持 | 使用场景 | |-----------------------|--------------|----------|----------|------------------------| | `lock()` | 阻塞 | ❌ | ❌ | 基础互斥 | | `tryLock()` | 非阻塞 | ❌ | ❌ | 快速失败逻辑 | | `tryLock(time,unit)` | 限时阻塞 | ✔️ | ✔️ | 避免长时间等待 | | `lockInterruptibly()`| 阻塞 | ✔️ | ❌ | 需响应中断的任务 | | `newCondition()` | - | - | - | 复杂线程协作 | > **最佳实践**: > 1. 始终在`try-finally`块中调用`unlock()`确保释放[^3] > 2. 优先使用`tryLock()`或带超时方法避免死 > 3. 使用`Condition`替代`Object.wait()`实现更精准的线程调度 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值