在Java并发编程中,锁是控制多个线程对共享资源访问的重要机制。下面分别简述普通锁、可重入锁和公平锁的概念:
-
普通锁(Intrinsic Locks 或 Monitor Locks):
- Java中的每个对象都有一个与之关联的内在锁或监视器锁,当线程进入synchronized代码块或方法时会自动获取该锁,退出时释放锁。
- synchronized关键字实现的锁是非公平的,即线程试图获取锁时,并不会按照等待顺序来分配,而是尝试直接获取锁,如果失败则进入阻塞队列。
-
可重入锁(ReentrantLock):
java.util.concurrent.locks.ReentrantLock
是Java并发包提供的一个API,它实现了更为灵活的锁机制,可以设置为公平或非公平。- 可重入意味着持有锁的线程可以再次获取同一个锁而不被阻塞,也就是所谓的“递归无阻塞”特性。这允许在同一个线程内嵌套调用加锁的方法而不会导致死锁。
- 通过构造函数可以选择创建公平或非公平的ReentrantLock实例。公平锁会严格按照线程请求锁的顺序来分配锁,而非公平锁则可能让等待时间短的线程插队获取锁,从而提高系统吞吐量但可能会导致某些线程饥饿。
-
公平锁(Fair Lock):
- 公平锁是一种线程调度策略,在分配锁时,保证所有等待的线程按到达的先后顺序获得锁。
- 在ReentrantLock中,如果设置了构造参数
true
,那么这个锁就会成为公平锁。公平锁的优势在于它能更好地避免线程饥饿问题,确保每个线程都有机会获得锁,但缺点是会增加上下文切换的开销,从而可能导致整体性能下降。
总结起来,Java并发编程中的锁可以根据需求选择不同类型的锁机制以平衡系统的并发效率和公平性。普通锁主要指的是使用synchronized
关键字实现的基础锁机制;而ReentrantLock作为更高级别的API提供了更多特性,其中就包括了可重入性和公平性选择。