Lock锁的使用

本文深入探讨了Lock锁的使用方法及其实现原理,为开发者提供了一种更细粒度的线程控制方式,有助于提高程序的并发性和效率。

Lock锁的使用


转载:http://www.cnblogs.com/dolphin0520/p/3923167.html

在 Java 中,使用 `Lock` 接口(尤其是 `ReentrantLock` 实现类)可以实现线程同步,从而确保多个线程对共享资源的访问是线程安全的。与 `synchronized` 关键字相比,`Lock` 提供了更灵活的机制,例如尝试获取、超时等待、可中断等待等特性,同时也支持更细粒度的控制[^2]。 ### 使用 ReentrantLock 实现线程同步 要使用 `ReentrantLock`,首先需要在类中声明一个 `ReentrantLock` 实例,并确保多个线程共享同一个对象。在访问共享资源之前调用 `lock()` 方法加,在访问结束后调用 `unlock()` 方法释放。为避免死,**必须在 `finally` 块中释放**,以确保无论是否发生异常,都能被正确释放[^3]。 #### 示例代码: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SharedResource { private static Lock lock = new ReentrantLock(); private static int counter = 0; public static void main(String[] args) { Thread t1 = new Thread(() -> { acquireLock(); }); Thread t2 = new Thread(() -> { acquireLock(); }); t1.start(); t2.start(); } private static void acquireLock() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + " 获取到了"); // 模拟执行操作 Thread.sleep(1000); counter++; System.out.println(Thread.currentThread().getName() + " 修改后计数器为: " + counter); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName() + " 释放了"); lock.unlock(); // 释放 } } } ``` 在上述代码中,两个线程通过共享同一个 `ReentrantLock` 实例来控制对共享变量 `counter` 的访问。每个线程在执行操作前必须获取,操作完成后释放,从而保证线程安全[^5]。 --- ### Lock 与 synchronized 的区别 - `synchronized` 是隐式,进入同步代码块时自动加,退出时自动释放;而 `ReentrantLock` 是显式,需要手动调用 `lock()` 和 `unlock()`。 - `ReentrantLock` 提供了比 `synchronized` 更丰富的功能,如尝试加、超时等待、可中断等待等。 - `ReentrantLock` 支持尝试获取失败后继续执行其他逻辑,而 `synchronized` 一旦进入阻塞状态则无法中断。 --- ### 注意事项 - 使用 `ReentrantLock` 时必须在 `finally` 块中调用 `unlock()`,以防止因异常导致未被释放,进而引发死。 - 多个线程必须共享同一个 `ReentrantLock` 实例,否则无法实现同步。 - 避免多个线程之间互相等待对方持有的,从而导致死[^3]。 --- ### 示例:线程安全的集合访问 以下示例展示了如何使用 `ReentrantLock` 确保多个线程安全地访问一个共享的 `ArrayList`: ```java import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SafeListAccess { private static List<Integer> list = new ArrayList<>(); private static Lock lock = new ReentrantLock(); public static void main(String[] args) { Runnable task = () -> { lock.lock(); try { for (int i = 0; i < 5; i++) { list.add(i); } System.out.println(Thread.currentThread().getName() + " 完成了插入操作"); } finally { lock.unlock(); } }; new Thread(task, "线程A").start(); new Thread(task, "线程B").start(); } } ``` 在此示例中,两个线程通过共享同一个 `ReentrantLock` 实例,确保对 `list` 的并发访问是线程安全的[^1]。 --- ### 总结 通过使用 `ReentrantLock`,可以更灵活地控制线程同步,避免线程安全问题。与 `synchronized` 相比,`ReentrantLock` 提供了更强大的功能和更细粒度的控制,但也需要开发者更谨慎地管理的获取与释放。合理使用 `ReentrantLock` 可以显著提升多线程程序的健壮性和性能。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值