设计公司注册资金多少合适怎么提高seo关键词排名
Java 锁机制详解:用“厕所门”和“防盗门”轻松理解多线程同步
目录
- 锁的作用
- synchronized 关键字
- ReentrantLock
- ReadWriteLock
- StampedLock
- 避免死锁的诀窍
- 总结与对比
锁的作用
生活中的例子:公共厕所一次只能进一人,门上的“有人/无人”标志就是锁。
程序中的作用:当多个线程操作共享资源(如银行账户余额)时,锁保证数据安全。
synchronized 关键字
1. 同步方法
class BankAccount {private int balance = 100;// 锁住整个对象public synchronized void withdraw(int amount) {if (balance >= amount) {System.out.println(Thread.currentThread().getName() + " 取款 " + amount);balance -= amount;}}
}
类比:厕所门自动上锁,其他人必须等待。
2. 同步代码块
public void withdraw(int amount) {// 只锁关键代码synchronized(this) { if (balance >= amount) {balance -= amount;}}
}
优势:缩小锁范围,提高效率。
ReentrantLock
import java.util.concurrent.locks.ReentrantLock;class TicketSeller {private int tickets = 10;private ReentrantLock lock = new ReentrantLock();public void sellTicket() {lock.lock(); // 手动加锁try {if (tickets > 0) {System.out.println(Thread.currentThread().getName() + " 卖出第 " + tickets--);}} finally {lock.unlock(); // 必须手动释放!}}
}
特点:
- 支持公平锁(
new ReentrantLock(true)
) - 可尝试获取锁(
tryLock()
) - 可中断等待(
lockInterruptibly()
)
类比:手动开关的防盗门,灵活控制进出规则。
ReadWriteLock
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;class Cache {private Object data = null;private ReadWriteLock rwLock = new ReentrantReadWriteLock();// 读操作:共享锁public Object getData() {rwLock.readLock().lock();try {return data;} finally {rwLock.readLock().unlock();}}// 写操作:独占锁public void updateData(Object newData) {rwLock.writeLock().lock();try {data = newData;} finally {rwLock.writeLock().unlock();}}
}
适用场景:读多写少(如商品库存查询)。
StampedLock
import java.util.concurrent.locks.StampedLock;class Point {private double x, y;private StampedLock lock = new StampedLock();// 乐观读:假设写操作很少发生public double distanceFromOrigin() {long stamp = lock.tryOptimisticRead();double currentX = x, currentY = y;if (!lock.validate(stamp)) { // 检查是否有写操作stamp = lock.readLock(); // 转为悲观读锁try {currentX = x;currentY = y;} finally {lock.unlockRead(stamp);}}return Math.sqrt(currentX * currentX + currentY * currentY);}
}
特点:在读多写少时性能更高,但实现复杂。
避免死锁的诀窍
经典死锁场景:两人在独木桥相遇,互不相让。
解决方案:
- 固定顺序获取锁:比如先锁 A 再锁 B。
- 设置超时时间:
tryLock(5, TimeUnit.SECONDS)
。
总结与对比
锁类型 | 特点 | 适用场景 |
---|---|---|
synchronized | 自动加锁/释放,简单但性能较低 | 简单同步需求 |
ReentrantLock | 手动控制,支持公平锁/条件变量 | 复杂同步场景 |
ReadWriteLock | 读写分离,提升读性能 | 读多写少(如缓存) |
StampedLock | 乐观读,性能最高但实现复杂 | 极高并发读,极少写 |
提示:实际开发中优先选择
synchronized
,需要高级功能时再考虑其他锁。