嘉定专业做网站,wordpress中文404,芜湖网站建设全包仅需800元,做网站都需要哪些软件StampedLock 是读写锁的实现#xff0c;对比 ReentrantReadWriteLock 主要不同是该锁不允许重入#xff0c;多了乐观读的功能#xff0c;使用上会更加复杂一些#xff0c;但是具有更好的性能表现。StampedLock 的状态由版本和读写锁持有计数组成。 获取锁方法返回一个邮戳对比 ReentrantReadWriteLock 主要不同是该锁不允许重入多了乐观读的功能使用上会更加复杂一些但是具有更好的性能表现。StampedLock 的状态由版本和读写锁持有计数组成。 获取锁方法返回一个邮戳表示和控制与锁状态相关的访问 这些方法的“尝试”版本可能会返回特殊值 0 来表示获取锁失败。 锁释放和转换方法需要邮戳作为参数如果它们与锁的状态不匹配则失败。
但是也是由于 StampedLock 大量使用自旋的原因ReentrantReadWriteLock 也使用了自旋但是没有 StampedLock 频繁CPU 的消耗理论上也比 ReentrantReadWriteLock 高。
StampedLock 非常适合写锁中的操作非常快的业务场景。因为读锁如果因为写锁而获取锁失败读锁会做重试获取和有限次的自旋的方式比较晚进入到等待队列中。如果在自旋过程中写锁能释放那么获取读锁的线程就能避免被操作系统阻塞和唤醒等耗资源操作增加读锁的响应效率。
三种模式 悲观读锁 与 ReentrantReadWriteLock 的读锁类似多个线程可以同时获取悲观读锁。这是一个共享锁允许多个线程同时读取共享资源。 乐观读锁 相当于直接操作数据不加任何锁。在操作数据前并没有通过 CAS 设置锁的状态仅仅通过位运算测试。如果当前没有线程持有写锁则简单地返回一个非 0 的 stamp 版本信息。返回 0 则说明有线程持有写锁。获取该 stamp 后在具体操作数据前还需要调用 validate 方法验证该 stamp 是否己经不可用。 写锁 与 ReentrantReadWriteLock的写锁类似写锁和悲观读锁是互斥的。虽然写锁与乐观读锁不会互斥但是在数据被更新之后之前通过乐观读锁获得的数据已经变成了脏数据需要自己处理这个。
StampedLock 的读写锁都是不可重入锁所以在获取锁后释放锁前不应该再调用会获取锁的操作以避免造成调用线程被阻塞。
在实际应用中StampedLock 可以用于那些读操作远多于写操作的场景例如缓存系统、数据报表生成等。在这些场景中StampedLock 可以显著提高并发性能同时保证数据的一致性和安全性。
最重要的一点 在使用时需要特别注意如果某个线程阻塞在StampedLock的readLock()或者writeLock()方法上时此 时调用阻塞线程的interrupt()方法中断线程会导致CPU飙升到100%。
所以尽量在写操作是非常快的场景下使用 这样读的时候乐观锁释放的非常快几乎达到无锁模式。
所有接口方法 经典案例
import java.util.concurrent.locks.StampedLock;public class StampedLockExample {private int inventory 100; // 初始库存为100private final StampedLock lock new StampedLock();// 扣减库存操作public void decreaseInventory(int quantity) {long stamp lock.writeLock(); // 获取写锁try {if (inventory quantity) {inventory - quantity; // 扣减库存System.out.println(成功减少库存 quantity , 当前的库存量: inventory);} else {System.out.println(未能减少库存库存不足);}} finally {lock.unlockWrite(stamp); // 释放写锁}}// 获取当前库存public int getInventory() {long stamp lock.tryOptimisticRead(); // 乐观读锁int currentInventory inventory;if (!lock.validate(stamp)) { // 检查乐观读锁是否有效stamp lock.readLock(); // 乐观读锁无效转为悲观读锁try {currentInventory inventory; // 获取当前库存} finally {lock.unlockRead(stamp); // 释放读锁}}return currentInventory; // 返回当前库存}public static void main(String[] args) {StampedLockExample manager new StampedLockExample();// 多个线程同时扣减库存Thread t1 new Thread(() - {manager.decreaseInventory(20); // 线程1扣减库存System.out.println(manager.getInventory());});Thread t2 new Thread(() - {manager.decreaseInventory(50); // 线程2扣减库存System.out.println(manager.getInventory());});t1.start();t2.start();}
}
官网案例 public class Point {private double x, y;private final StampedLock sl new StampedLock();public void move(double deltaX, double deltaY) {使用写锁-独占操作并返回一个邮票long stamp sl.writeLock();try {x deltaX;y deltaY;} finally {使用邮票来释放写锁sl.unlockWrite(stamp); }}// 使用乐观读锁访问共享资源// 注意乐观读锁在保证数据一致性上需要拷贝一份要操作的变量到方法栈并且在操作数据时候可能其 // 他写线程已经修改了数据而我们操作的是方法栈里面的数据也就是一个快照所以最多返回的不是 // 最新的数据但是一致性还是得到保障的。public double distanceFromOrigin() {使用乐观读锁-并返回一个邮票乐观读不会阻塞写入操作从而解决了写操作线程饥饿问题。long stamp sl.tryOptimisticRead(); 拷贝共享资源到本地方法栈中double currentX x, currentY y; if (!sl.validate(stamp)) { 如果验证乐观读锁的邮票失败说明有写锁被占用可能造成数据不一致所以要切换到普通读锁模式。stamp sl.readLock(); try {currentX x;currentY y;} finally {sl.unlockRead(stamp);}}// 如果验证乐观读锁的邮票成功说明在此期间没有写操作进行数据修改那就直接使用共享数据。return Math.sqrt(currentX * currentX currentY * currentY);}// 锁升级读锁-- 写锁public void moveIfAtOrigin(double newX, double newY) { // upgrade// Could instead start with optimistic, not read modelong stamp sl.readLock();try {while (x 0.0 y 0.0) {读锁转换为写锁long ws sl.tryConvertToWriteLock(stamp); if (ws ! 0L) {如果升级到写锁成功就直接进行写操作。stamp ws;x newX;y newY;break;} else {//如果升级到写锁失败那就释放读锁且重新申请写锁。sl.unlockRead(stamp);stamp sl.writeLock();}}} finally {//释放持有的锁。sl.unlock(stamp);}}}StampedLock和ReentrantReadWriteLock之间的区别
锁的类型与特性 StampedLock提供了乐观读、悲观读和写锁三种模式。乐观读模式允许在写锁未被持有时进行无锁读取通过验证戳记stamp来确保数据的一致性。这种模式减少了锁的竞争提高了吞吐量。ReentrantReadWriteLock允许多个读线程同时访问但写线程在访问时必须独占。它支持锁的重入即同一线程可以多次获取同一把锁。 性能 StampedLock通常比ReentrantReadWriteLock具有更高的性能特别是在读多写少的场景下。由于乐观读的存在它能够在无竞争的情况下避免不必要的锁开销。ReentrantReadWriteLock在读操作远多于写操作的场景中表现良好但写锁的饥饿问题和锁降级操作可能影响其性能。 实现机制 StampedLock并非基于AQSAbstractQueuedSynchronizer实现而是使用了自己的同步等待队列和状态设计。其状态为一个long型变量与ReentrantReadWriteLock的设计不同。ReentrantReadWriteLock基于AQS实现通过内部维护的读写锁来实现多线程间的同步。 使用场景 StampedLock更适合于读多写少且对性能要求较高的场景尤其是当数据争用不严重时。它能够有效减少锁的竞争提高系统的吞吐量。ReentrantReadWriteLock适用于需要重入锁或需要在写操作后降级为读锁的场景。它提供了更严格的访问控制但可能在某些情况下牺牲了一定的性能。 锁的获取与释放 StampedLock在获取锁时会返回一个戳记stamp用于后续的锁释放或转换。这个戳记代表了锁的状态有助于在释放锁时验证数据的一致性。ReentrantReadWriteLock没有戳记的概念锁的获取和释放相对简单直接。
综上所述StampedLock和ReentrantReadWriteLock各有其特点和适用场景。在选择使用哪种锁时应根据具体的应用需求和性能要求来做出决策。 点赞 -收藏 -关注 有问题在评论区或者私信我-收到会在第一时间回复