关于Lock.tryLock():线程可执行不同任务的技术疑问
关于Java多线程中“获取锁失败时执行其他任务”的实现解析
嘿,这个问题问得特别戳痛点!很多刚摸并发的同学都会有这个疑惑——直觉上总觉得线程就该一条路走到黑,拿不到锁就等着呗,怎么还能跑去做别的?其实核心在于Java给了我们灵活控制线程行为的工具,不是线程天生会“分身”,而是我们可以用API让它在拿不到锁的时候走分支逻辑。
为什么能在获取锁失败时执行其他任务?
首先要打破一个误解:线程的执行流程是我们自己写的,不是固定死的“必须等锁”。java.util.concurrent.locks包提供了非阻塞式的锁获取方式,最典型的就是Lock接口的tryLock()方法——它不会让线程陷入无限阻塞,而是在拿不到锁时直接返回false,这时候我们就能在代码里写分支,让线程去执行其他任务。
举个真实场景:比如你写了一个处理用户订单的线程,它需要获取锁去操作数据库,但如果锁被其他线程占用了,它不用傻等,而是可以先去处理之前缓存的用户通知消息,或者清理临时文件,等一会儿再重试拿锁。
实际代码实现案例
下面是一个用ReentrantLock实现的完整例子,你可以直接运行看效果:
import java.util.concurrent.locks.ReentrantLock; public class TryLockDemo { // 定义一个可重入锁 private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { // 线程1:尝试获取锁,失败则执行临时任务 Thread businessThread = new Thread(() -> { while (true) { // 尝试获取锁,最多等待1秒(也可以用无参tryLock(),立即返回结果) if (lock.tryLock()) { try { System.out.println(Thread.currentThread().getName() + " 拿到锁,开始处理核心订单业务..."); // 模拟核心业务耗时 Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { // 必须释放锁,否则会造成死锁 lock.unlock(); System.out.println(Thread.currentThread().getName() + " 释放锁,核心业务处理完成"); // 处理完就退出循环 break; } } else { // 获取锁失败,执行临时任务 System.out.println(Thread.currentThread().getName() + " 没拿到锁,先去处理临时任务:清理用户缓存..."); try { // 模拟临时任务耗时 Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } }, "订单处理线程"); // 线程2:先占用锁,模拟锁被占用的场景 Thread lockOccupyThread = new Thread(() -> { lock.lock(); try { System.out.println(Thread.currentThread().getName() + " 占用锁,处理库存更新业务..."); Thread.sleep(3000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); System.out.println(Thread.currentThread().getName() + " 释放锁"); } }, "库存更新线程"); lockOccupyThread.start(); businessThread.start(); } }
运行后你会看到:订单处理线程一开始拿不到锁,会反复执行“清理缓存”的临时任务,直到库存更新线程释放锁后,它才会切换到核心订单业务的处理。
关键知识点梳理
lock()方法:是阻塞式的,线程拿不到锁就会一直卡着,这时候确实只能等,没法做别的。tryLock()方法:非阻塞式的,有两种常用用法:tryLock():立即返回结果,能拿到锁就返回true,否则falsetryLock(long time, TimeUnit unit):在指定时间内尝试拿锁,超时还拿不到就返回false
- 线程的灵活性:我们通过判断
tryLock()的返回值,就能完全控制线程在拿锁失败时的行为——可以去做其他任务、可以定时重试、甚至可以直接放弃,完全由你的业务逻辑决定。
说白了,不是线程“自动会去做别的”,而是我们利用Java提供的非阻塞锁API,给线程写了“拿不到锁就去做X”的逻辑,这才实现了所谓的“获取锁失败时执行其他任务”。
内容的提问来源于stack exchange,提问作者CuriousMind
相关产品推荐
相关产品推荐

