2025年06月29日/ 浏览 6
在多线程编程中,锁是协调资源访问的核心机制。Java的锁体系可分为三个维度:
认为并发冲突必然发生,典型代表是synchronized
关键字:
java
public synchronized void transfer(Account target, int amount) {
this.balance -= amount;
target.balance += amount;
}
特性:
– 独占资源直至释放
– 适合写操作频繁场景
– 可能引发线程阻塞
假设冲突概率低,采用版本号/CAS机制实现。如AtomicInteger
:
java
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // 基于CAS操作
实现要点:
– 比较并交换(Compare-And-Swap)
– 适合读多写少场景
– 需处理失败重试
按照线程申请顺序分配资源,如:
java
ReentrantLock fairLock = new ReentrantLock(true);
特点:
– 避免线程饥饿
– 上下文切换开销较大
允许插队抢占资源,默认实现:
java
ReentrantLock nonFairLock = new ReentrantLock();
优势:
– 吞吐量更高
– 可能出现长时等待
传统synchronized
在竞争激烈时会升级为重量级锁,涉及操作系统互斥量。
通过CAS操作尝试获取锁,失败才升级为重量级锁。JVM的锁优化包括:
– 偏向锁
– 自旋锁
– 锁消除
允许同一线程多次获取同一把锁:
“`java
ReentrantLock lock = new ReentrantLock();
void recursiveMethod(int n) {
lock.lock();
try {
if(n > 0) {
recursiveMethod(n-1);
}
} finally {
lock.unlock();
}
}
“`
优势:
– 避免自我死锁
– 支持条件变量(Condition)
典型死锁场景:
“`java
// 线程1
synchronized(resourceA) {
synchronized(resourceB) {…}
}
// 线程2
synchronized(resourceB) {
synchronized(resourceA) {…}
}
“`
预防策略:
1. 按固定顺序获取资源
2. 设置超时时间(tryLock)
3. 使用死锁检测工具
ReadWriteLock
通过合理选择锁机制,开发者可以在线程安全与系统性能之间取得平衡。理解不同锁的特性及适用场景,是构建高并发系统的关键基础。
“`