使用 stampedlock实现高效读写
1. 它是什么?
stampedlock
是 java 8 引入的高性能锁,提供了三种锁模式:写锁、悲观读锁和乐观读锁。
与传统的 reentrantreadwritelock
相比,stampedlock
更注重性能,特别适合读多写少的场景。
- 写锁:阻塞所有其他操作(类似独占锁)。
- 悲观读锁:共享锁,允许多个线程读取,但会阻塞写操作。
- 乐观读锁:一种非阻塞读操作,允许并发写操作,并在必要时验证数据一致性。
2. 它的使用场景是什么?
- 读多写少的场景:如缓存、配置数据读取等场景,
stampedlock
的乐观读锁可以显著提高性能。 - 需要快速读锁验证的场景:在乐观读的情况下,可以验证数据的一致性并在必要时降级为悲观读锁。
- 写锁需要优先处理的场景:避免传统读写锁中写线程因读操作而长期饥饿的问题。
3. 它有哪些 api?
核心 api
方法名称 | 描述 |
---|---|
writelock() | 获取写锁,返回一个 stamp(锁标识)。 |
readlock() | 获取悲观读锁,返回一个 stamp(锁标识)。 |
tryoptimisticread() | 获取乐观读锁,返回一个 stamp,非阻塞,适合快速读取。 |
unlockwrite(long stamp) | 释放写锁,需要传入获取锁时返回的 stamp。 |
unlockread(long stamp) | 释放悲观读锁,需要传入获取锁时返回的 stamp。 |
validate(long stamp) | 验证乐观读锁期间是否有写操作发生,返回 true 表示数据未被修改。false 表示数据已经被修改过 |
扩展 api
方法名称 | 描述 |
---|---|
trywritelock() | 尝试获取写锁,如果未成功立即返回。 |
tryreadlock() | 尝试获取读锁,如果未成功立即返回。 |
tryconverttowritelock(long stamp) | 尝试将当前锁转换为写锁,成功时返回新 stamp,否则返回 0。 |
tryconverttoreadlock(long stamp) | 尝试将当前锁转换为读锁,成功时返回新 stamp,否则返回 0。 |
iswritelocked() | 检查当前锁是否有写锁被占用。 |
isreadlocked() | 检查当前锁是否有读锁被占用。 |
4. 它的使用方式
(1)写锁的使用
public void updatevalue(double deltax, double deltay) { long stamp = lock.writelock(); // 获取写锁 try { x += deltax; y += deltay; } finally { lock.unlockwrite(stamp); // 释放写锁 } }
(2)悲观读锁的使用
public double readvalue() { long stamp = lock.readlock(); // 获取读锁 try { return math.sqrt(x * x + y * y); } finally { lock.unlockread(stamp); // 释放读锁 } }
(3)乐观读锁的使用
public double readvalueoptimistically() { 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); }
(4)锁升级的使用
public void conditionalupdate(double deltax, double deltay) { long stamp = lock.readlock(); // 获取悲观读锁 try { if (x == 0 && y == 0) { // 检查条件 stamp = lock.tryconverttowritelock(stamp); // 升级为写锁 if (stamp == 0l) { // 如果升级失败 stamp = lock.writelock(); // 显式获取写锁 } x += deltax; y += deltay; } } finally { lock.unlock(stamp); // 释放锁 } }
5. 它有哪些注意事项
(1)stampedlock 不可重入 stampedlock 不支持重入。如果同一线程尝试再次获取锁(无论读锁还是写锁),会导致死锁。
(2)锁释放需要传入正确的 stamp 每次加锁时都会返回一个唯一的 stamp,在释放锁时需要传入对应的 stamp,否则会抛出 illegalmonitorstateexception。
(3)写优先策略 stampedlock 优先满足写锁请求,避免了读写锁可能出现的写线程饥饿问题。
(4)线程安全 stampedlock 是线程安全的,但不支持条件变量(condition),因此无法直接使用 wait 或 notify。
(5)适用场景 适合 读多写少 的场景。 不适合写频繁的场景,因为写锁的争用会导致性能下降。
总结
stampedlock 是 java 并发工具库中的一颗“冷门宝石”,它通过乐观读锁提供了高效的非阻塞读机制,同时避免了写线程饥饿的问题。熟悉其 api 和使用场景,能够帮助你在性能敏感的场景中实现更高效的并发控制!
以上就是java使用stampedlock实现高效读写功能的详细内容,更多关于java stampedlock高效读写的资料请关注代码网其它相关文章!
发表评论