Lock接口

打印 上一主题 下一主题

主题 1885|帖子 1885|积分 5655

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
java.util.concurrent.locks.Lock 接口是Java并发包中的一部分,它提供了比内置锁(即 synchronized 关键字)更机动和强大的锁机制。通过使用 Lock 接口及其相干实现类,开发者可以获得更多的功能选项来控制线程间的同步行为,例如可中断的锁等候、超时获取锁、公平锁等。这些特性使得 Lock 在某些特定场景下更加适适用于并发编程。
为什么需要Lock接口?

尽管 synchronized 是一种简朴而有效的同步手段,但它也有一些范围性:


  • 缺乏机动性:无法指定是否等候获取锁的时间限制,也不能被中断。
  • 单一入口/出口:一旦进入同步块或方法,必须等到退出后才气开释锁;不能在代码中心开释锁再重新获取。
  • 没有实行加锁的功能:假如不想阻塞当火线程直到获得锁,则没有直接的方法可以做到这一点。
  • 不支持公平性:多个线程竞争同一个锁时,不能保证按照请求顺序依次获得锁。
为了解决上述题目,并提供更加丰富的功能,Java引入了 Lock 接口以及它的几种常见实现方式。


Lock接口的主要方法

Lock 接口界说了一系列用于管理和操纵锁的方法,主要包罗以下几个方面:
锁操纵



  • void lock():获取锁。假如锁已被其他线程占用,则当火线程将被阻塞,直到该锁可用为止。
  • void unlock():开释锁。只有当调用此方法的线程拥有这个锁时才有效果,否则可能会抛出非常。
  • void lockInterruptibly() throws InterruptedException:与 lock() 类似,但是在等候过程中允许被中断。假如线程正在等候锁并且收到了中断信号,则会抛出 InterruptedException 并返回。
  • boolean tryLock():实行非阻塞地获取锁。假如立刻可用,则成功并返回 true;否则失败并返回 false。
  • boolean tryLock(long time, TimeUnit unit) throws InterruptedException:实行在指定时间内获取锁。假如在此期间内成功获取到锁,则返回 true;若超时仍未获得,则返回 false。同样地,等候期间也可以被中断。
条件变量(Condition)

除了根本的锁操纵外,Lock 接口还支持条件变量的概念,这类似于传统的对象监视器中的 wait() 和 notify() 方法。每个 Lock 实例都可以关联一个或多个 Condition 对象,它们允许线程以更加细粒度的方式举行协调。


  • Condition newCondition():创建一个新的条件实例,与当前锁绑定在一起。


Lock接口的实现类

Java 提供了几种常用的 Lock 接口实现,每种都有其特点和适用场景:
ReentrantLock

ReentrantLock 是最常用的 Lock 实现之一,它实现了可重入锁,这意味着持有锁的线程可以在不开释现有锁的情况下再次获取雷同的锁。此外,ReentrantLock 还提供了两种构造函数情势:默认情况下是非公平锁,但也可以创建公平锁,确保线程按照请求锁的顺序依次获得锁。
  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. public class Counter {
  4.     private int count = 0;
  5.     private final Lock lock = new ReentrantLock();
  6.     public void increment() {
  7.         lock.lock();
  8.         try {
  9.             count++;
  10.         } finally {
  11.             lock.unlock(); // 确保无论发生什么都释放锁
  12.         }
  13.     }
  14.     public int getCount() {
  15.         return count;
  16.     }
  17. }
复制代码
ReadWriteLock

ReadWriteLock 接口表示读写锁,它允许多个读线程同时访问共享资源,但在有写线程时禁止所有其他线程(包罗读和写)。这种锁非常适合于读多写少的应用场景,由于它能提高并发性能。
  1. import java.util.concurrent.locks.ReadWriteLock;
  2. import java.util.concurrent.locks.ReentrantReadWriteLock;
  3. public class Cache<K, V> {
  4.     private final Map<K, V> map = new HashMap<>();
  5.     private final ReadWriteLock rwl = new ReentrantReadWriteLock();
  6.     public V get(K key) {
  7.         rwl.readLock().lock();
  8.         try {
  9.             return map.get(key);
  10.         } finally {
  11.             rwl.readLock().unlock();
  12.         }
  13.     }
  14.     public void put(K key, V value) {
  15.         rwl.writeLock().lock();
  16.         try {
  17.             map.put(key, value);
  18.         } finally {
  19.             rwl.writeLock().unlock();
  20.         }
  21.     }
  22. }
复制代码
StampedLock

StampedLock 是 Java 8 引入的一种高性能的读写锁实现,它不仅支持传统的读锁和写锁,还增长了乐观读锁的功能。乐观读锁假设在读取数据的过程中不会发生修改,因此不需要实际锁定资源,只有当检测到冲突时才会回退并接纳悲观计谋。这种方式可以在肯定程度上减少争用,提升吞吐量。
  1. import java.util.concurrent.locks.StampedLock;
  2. public class Point {
  3.     private double x, y;
  4.     private final StampedLock sl = new StampedLock();
  5.     void move(double deltaX, double deltaY) { // an exclusively locked method
  6.         long stamp = sl.writeLock();
  7.         try {
  8.             x += deltaX;
  9.             y += deltaY;
  10.         } finally {
  11.             sl.unlockWrite(stamp);
  12.         }
  13.     }
  14.     double distanceFromOrigin() { // A read-only method
  15.         long stamp = sl.tryOptimisticRead();
  16.         double currentX = x, currentY = y;
  17.         if (!sl.validate(stamp)) {
  18.             stamp = sl.readLock();
  19.             try {
  20.                 currentX = x;
  21.                 currentY = y;
  22.             } finally {
  23.                 sl.unlockRead(stamp);
  24.             }
  25.         }
  26.         return Math.sqrt(currentX * currentX + currentY * currentY);
  27.     }
  28. }
复制代码


使用Lock接口的优势


  • 更多功能选项:如前所述,Lock 接口提供的方法比 synchronized 更加丰富,可以或许满足不同的需求。
  • 更好的性能表现:对于某些范例的锁(如读写锁),Lock 可以显著提高并发性能。
  • 清晰的语义表达:显式地获取和开释锁的操纵让代码意图更加明白,便于理解和维护。
  • 易于扩展:基于接口的设计使得我们可以很容易地更换不同范例的锁实现,或者自界说新的锁行为。


注意事项

虽然 Lock 接口带来了诸多利益,但在实际应用中也需要注意以下几点:


  • 确保总是开释锁:无论是否发生非常,都应当保证最终会调用 unlock() 方法开释锁,以免造成死锁或其他不可预测的行为。通常发起使用 try-finally 或者 Java 7+ 的 try-with-resources 语法来保证这一点。
  • 避免长时间持有锁:尽量缩短持有锁的时间,尤其是写锁,以减少对其他线程的影响。
  • 理解锁的开销:尽管 Lock 接口提供了额外的功能,但同时也可能带来肯定的性能损失。因此,在选择使用哪种同步机制时要权衡利弊。


结语

感谢您的阅读!假如您对 Lock 接口或其他 Java 并发编程话题有任何疑问或见解,接待继承探讨。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表