Java进阶DAY31-16: Lock锁
在Java的并发编程中,java.util.concurrent.locks.Lock
接口提供了比传统的synchronized
方法和语句更复杂的锁定操作。它们允许更灵活的结构,可以拥有不同的属性(如可重入性、公平性)。Lock
接口的实现提供了用于多线程访问共享资源的锁定控制,使得数据的访问更加安全。
Lock接口的主要特点
- 显式锁定和解锁:与
synchronized
自动加锁和解锁的方式不同,Lock
需要手动启动和停止锁定。 - 尝试非阻塞获取锁:
tryLock()
方法尝试获取锁,如果锁不可用,立即返回而不是等待。 - 可中断的锁获取尝试:
lockInterruptibly()
允许在等待锁的过程中响应中断。 - 支持超时:
tryLock(long time, TimeUnit unit)
允许等待锁一定的时间,超时未能获取则返回。 - 公平锁:某些
Lock
实现支持公平锁,即等待时间最长的线程将获得锁(例如ReentrantLock
的公平模式)。
使用Lock锁
示例:使用ReentrantLock
ReentrantLock
是Lock
接口的一个实现,支持完全互斥的锁定机制。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Counter {
private final Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock(); // 开始锁定
try {
count++;
} finally {
lock.unlock(); // 确保在finally块中解锁
}
}
public int getCount() {
return count;
}
}
在这个例子中,increment
方法通过lock
和unlock
方法显式地控制着对count
变量的访问,确保了线程安全。
Lock与synchronized的比较
- 灵活性:
Lock
提供了比synchronized
更高的灵活性,包括尝试非阻塞地获取锁、可中断的锁获取等。 - 控制细粒度:
Lock
允许分离读和写操作,使得多个读线程可以同时访问共享资源,提高了效率(如ReentrantReadWriteLock
)。 - 性能:在高竞争环境下,
Lock
可能提供比synchronized
更好的性能,尤其是Lock
提供的一些高级功能,如公平性、可中断锁等。
注意事项
- 避免死锁:与
synchronized
一样,使用Lock
时也需要注意避免死锁。 - 确保释放锁:在
finally
块中释放锁是一个好习惯,这样可以防止因异常而导致锁永远不被释放。
结论
Lock
接口为Java并发编程提供了一种更灵活、更强大的锁定机制。通过显式的锁定和解锁操作,它提供了一种更细粒度的控制方式,使得开发者可以根据具体需求构建更为复杂的并发控制逻辑。不过,使用Lock
时也需要谨慎,以避免死锁和确保锁的正确释放。