如何选择适当的锁粒度?
下文笔者讲述java代码中,选择合适锁粒度的方法及示例分享,如下所示
为什么要选择匹配自己的锁粒度呢?
锁粒度的选择直接影响程序的性能、吞吐量和线程安全 选择适当的锁粒度,意味着在线程安全与并发效率之间找到最佳平衡点
锁粒度简介
| 类型 | 含义 | 示例 |
| 粗粒度锁 | 锁定范围大 (如整个对象或方法) | `synchronized` 方法 |
| 细粒度锁 | 锁定范围小 (如某个字段、数据块) | `ReentrantLock` + 局部同步 |
锁粒度对系统影响
| 特性 | 粗粒度锁 | 细粒度锁 |
| 并发性能 | 较低(线程竞争激烈) | 高(减少阻塞) |
| 实现复杂度 | 简单 | 复杂 |
| 资源开销 | 小(锁数量少) | 大(管理多个锁) |
| 适用场景 | 单线程或低并发 | 高并发、大规模访问 |
业务场景选择合适的锁粒度示例
✅ 场景一:低并发、操作简单 → 使用粗粒度锁
- 推荐锁:
- `synchronized`
- `ReentrantLock`
- 原因:
- 实现简单,维护成本低。
- 不需要为低并发引入复杂的锁机制。
- 示例:
```java
public synchronized void addData(Data data) {
datalist.add(data);
}
✅ 场景二:高并发读写共享资源 → 使用细粒度锁或分段锁
- 推荐锁:
- `ReentrantReadWriteLock`
- `StampedLock`
- `ConcurrentHashMap`(内部使用分段锁)
- 原因:
- 提高并发访问效率。
- 减少线程阻塞。
-例(使用 `ConcurrentHashMap`)
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key1", 100);
Integer value = map.get("key1");
✅ 场景三:多线程协作任务 → 使用条件变量 + 细粒度锁
- 推荐锁:
- `ReentrantLock` + `Condition`
- 原因:
- 可以实现更灵活的等待/通知机制。
- 控制不同线程之间的协作。
-例:
ReentrantLock lock = new ReentrantLock();
Condition notFull = lock.newCondition();
Condition notEmpty = lock.newCondition();
lock.lock();
try {
while (queue.size() == capacity) {
notFull.await();
}
queue.add(item);
notEmpty.signal();
} finally {
lock.unlock();
}
✅ 场景四:资源池、连接池等控制访问数量 → 使用 `Semaphore`
- 推荐锁:
- `Semaphore`
- 原因:
- 控制同时访问线程数量。
- 不是对数据加锁,而是对资源访问进行限流。
-例:
Semaphore semaphore = new Semaphore(5); // 最多允许 5 个线程访问
semaphore.acquire();
try {
// 访问资源
} finally {
semaphore.release();
}
锁粒度常见误区与建议
| 误区 | 正确认知 |
| 锁越细越好 | 锁太多会增加上下文切换 和内存开销 |
| 所有方法都加锁 | 应只对共享状态加锁, 非共享部分无需同步 |
| 忽略锁的可重入性 | 使用 `ReentrantLock` 或 `synchronized` 可避免死锁 |
| 不考虑公平性 | 在资源争用激烈的场景下, 应启用公平锁(如 `new ReentrantLock(true)`) |
各种锁粒度选择对比
| 场景 | 推荐锁类型 | 锁粒度建议 |
| 低并发、简单操作 | `synchronized`/`ReentrantLock` | 粗粒度 |
| 高并发读多写少 | `ReentrantReadWriteLock`/`StampedLock` | 中等/细粒度 |
| 共享资源访问控制 | Semaphore` | 中等 |
| 多线程协作任务 | `ReentrantLock` + `Condition` | 细粒度 |
| 数据结构并发访问 | `ConcurrentHashMap`, `CopyOnWriteArrayList` | 分段锁/内部优化 |
锁粒度选择注意事项
1.优先保证线程安全:
在多线程访问共享资源时,必须加锁 2.尽量缩小锁的持有时间:
只锁定真正需要保护的部分 3.根据并发程度调整锁粒度:
并发越高,锁越细 4.结合实际业务需求选择锁类型:
不盲目追求“最先进”的锁,
而是“最适合当前场景”的锁
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


