如何选择适当的锁粒度?
下文笔者讲述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.结合实际业务需求选择锁类型:
不盲目追求“最先进”的锁,
而是“最适合当前场景”的锁
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。