概要
在Java中,synchronized 关键字用于实现同步,以确保在多线程环境下对共享资源的访问是线程安全的。然而,synchronized 实现的锁机制默认被认为是非公平锁。以下是关于 synchronized 为何是非公平锁的解释:
1. 非公平锁的定义
非公平锁是指当一个线程释放锁时,等待队列中的线程不一定按照它们等待的顺序来获取锁,而是允许其他正在等待的线程或者新来尝试获取锁的线程进行竞争。也就是说,非公平锁不保证等待时间最长的线程会优先获得锁。
2. synchronized 作为非公平锁的原因
- 效率优先:synchronized 的设计初衷是提供线程同步的功能,而非确保严格的公平性。非公平锁允许新来的线程直接尝试获取锁,这有助于减少线程切换的开销,从而提高效率。
- 避免饥饿现象:虽然非公平锁可能导致某些线程等待时间变长,但在实际使用中,由于线程调度的不确定性,很难出现某个线程长时间无法获取锁的情况(即饥饿现象)。
3. 非公平锁的特点
- 性能较好:因为减少了线程切换的开销,所以非公平锁通常具有更好的性能。
- 可能产生饥饿现象:虽然这种情况在实际中较少出现,但在某些特定场景下,如果某个线程一直竞争失败,可能会导致其长时间无法获取锁。
4. 如何实现公平锁
如果需要更严格的公平性,可以使用 ReentrantLock 类来替代 synchronized。ReentrantLock 允许通过构造函数指定是否为公平锁。当设置为公平锁时,它会按照等待队列中线程等待的顺序来分配锁。
总结
synchronized 作为Java中的内置锁机制,默认实现为非公平锁。这是基于性能考虑和避免饥饿现象的折中方案。在大多数场景下,非公平锁的性能优势足以弥补其可能带来的不公平性。然而,在需要更严格公平性的场景中,可以使用 ReentrantLock 类来实现公平锁。