JUC并发编程 -- ReentrantLock可重入锁(可重入 & 可打断 & 锁超时 & 锁超时-解决哲学家就餐)
2021/9/5 20:07:13
本文主要是介绍JUC并发编程 -- ReentrantLock可重入锁(可重入 & 可打断 & 锁超时 & 锁超时-解决哲学家就餐),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. ReentrantLock可重入锁
相对于 synchronized 它具备如下特点:
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量(相当于有多个EntryList)
- 与 synchronized 一样,都支持可重入
基本语法:
// 获取锁 reentrantLock.lock(); try { // 临界区 } finally { // 释放锁 reentrantLock.unlock(); }
1.1 可重入
- 可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁。
- 如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住。
示例代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test22") public class Test22 { private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { lock.lock(); try { log.debug("Enter Main"); m1(); } catch (Exception e) { lock.unlock(); } } public static void m1() { lock.lock(); try { log.debug("Enter m1"); m2(); } catch (Exception e) { lock.unlock(); } } public static void m2() { lock.lock(); try { log.debug("Enter m2"); } catch (Exception e) { lock.unlock(); } } }
运行结果:
1.2 可打断
- 对象在获得锁后,可以被打断
- ReentrantLock对象的lockInterruptibly()方法可以被打断,ReentrantLock对象的lock方法不可被打断。
- 被动打断线程(其他线程调用interrupt方法)
示例代码:
@Slf4j(topic = "c.Test22") public class Test22 { private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("启动..."); try { // ReentrantLock对象的lockInterruptibly()方法可以被打断 lock.lockInterruptibly(); } catch (InterruptedException e) { e.printStackTrace(); log.debug("等锁的过程中被打断"); return; } try { log.debug("获得了锁"); } finally { lock.unlock(); } }, "t1"); lock.lock(); log.debug("获得了锁"); t1.start(); try { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t1.interrupt(); log.debug("执行打断"); } finally { lock.unlock(); } }
运行结果:
1.3 锁超时
lock.tryLock(2, TimeUnit.SECONDS)方法可以设置尝试获取锁的最大等待时间,如果超过了最大等待时间,则获取不到锁。这个方法返回一个布尔值,如果或得到了锁,则返回true否则返回false。如果这个方法不加参数,那么会一直尝试去获取锁。
1.3.1 示例代码(t1线程获取不到锁):
代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test22") public class Test22 { private static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { log.debug("尝试获得锁"); try { if (!lock.tryLock(2, TimeUnit.SECONDS)) { log.debug("获取不到锁"); return; } } catch (InterruptedException e) { e.printStackTrace(); log.debug("获取不到锁"); return; } try { log.debug("获得到锁"); } finally { lock.unlock(); } }, "t1"); lock.lock(); log.debug("获得到锁"); t1.start(); Thread.sleep(3000); log.debug("释放了锁"); lock.unlock(); } }
运行结果:
1.3.2 示例代码(t1线程获取到锁):
代码:
运行结果:
1.4 锁超时-解决哲学家就餐
代码:
package tian; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.locks.ReentrantLock; @Slf4j(topic = "c.Test23") public class Test23 { public static void main(String[] args) { Chopstick c1 = new Chopstick("1"); Chopstick c2 = new Chopstick("2"); Chopstick c3 = new Chopstick("3"); Chopstick c4 = new Chopstick("4"); Chopstick c5 = new Chopstick("5"); new Philosopher("苏格拉底", c1, c2).start(); new Philosopher("柏拉图", c2, c3).start(); new Philosopher("亚里士多德", c3, c4).start(); new Philosopher("赫拉克利特", c4, c5).start(); new Philosopher("阿基米德", c5, c1).start(); } } @Slf4j(topic = "c.Philosopher") class Philosopher extends Thread { Chopstick left; Chopstick right; public Philosopher(String name, Chopstick left, Chopstick right) { super(name); this.left = left; this.right = right; } @Override public void run() { while (true) { // 尝试获得左手筷子 if (left.tryLock()) { try { // 尝试获得右手筷子 if (right.tryLock()) { try { eat(); } finally { right.unlock(); } } } finally { // 如果没有获得右手的筷子 则释放自己手里的筷子 这里是解决哲学家就餐问题的关键 left.unlock(); } } } } private void eat() { log.debug("eating..."); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } class Chopstick extends ReentrantLock { String name; public Chopstick(String name) { this.name = name; } @Override public String toString() { return "筷子{" + name + '}'; } }
运行结果:
这篇关于JUC并发编程 -- ReentrantLock可重入锁(可重入 & 可打断 & 锁超时 & 锁超时-解决哲学家就餐)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-10Rakuten 乐天积分系统从 Cassandra 到 TiDB 的选型与实战
- 2025-01-09CMS内容管理系统是什么?如何选择适合你的平台?
- 2025-01-08CCPM如何缩短项目周期并降低风险?
- 2025-01-08Omnivore 替代品 Readeck 安装与使用教程
- 2025-01-07Cursor 收费太贵?3分钟教你接入超低价 DeepSeek-V3,代码质量逼近 Claude 3.5
- 2025-01-06PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”
- 2025-01-05Easysearch 可搜索快照功能,看这篇就够了
- 2025-01-04BOT+EPC模式在基础设施项目中的应用与优势
- 2025-01-03用LangChain构建会检索和搜索的智能聊天机器人指南
- 2025-01-03图像文字理解,OCR、大模型还是多模态模型?PalliGema2在QLoRA技术上的微调与应用