如何选择适当的锁粒度?

欢喜 Java经验 发布时间:2025-06-09 09:48:47 阅读数:133 1
下文笔者讲述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.结合实际业务需求选择锁类型:
不盲目追求“最先进”的锁,
而是“最适合当前场景”的锁
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202506/17494379918491.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者