当前位置: 首页 > news >正文

网站开发课程培训企业微信开放平台

网站开发课程培训,企业微信开放平台,运营公众号还是做网站,wordpress不显示 头像StampedLock 是读写锁的实现,对比 ReentrantReadWriteLock 主要不同是该锁不允许重入,多了乐观读的功能,使用上会更加复杂一些,但是具有更好的性能表现。StampedLock 的状态由版本和读写锁持有计数组成。 获取锁方法返回一个邮戳&…

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%。

所以尽量在写操作是非常快的场景下使用, 这样读的时候乐观锁释放的非常快,几乎达到无锁模式。

所有接口方法

image.png
image.png
image.png

经典案例

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之间的区别

  1. 锁的类型与特性
    • StampedLock:提供了乐观读、悲观读和写锁三种模式。乐观读模式允许在写锁未被持有时进行无锁读取,通过验证戳记(stamp)来确保数据的一致性。这种模式减少了锁的竞争,提高了吞吐量。
    • ReentrantReadWriteLock:允许多个读线程同时访问,但写线程在访问时必须独占。它支持锁的重入,即同一线程可以多次获取同一把锁。
  2. 性能
    • StampedLock:通常比ReentrantReadWriteLock具有更高的性能,特别是在读多写少的场景下。由于乐观读的存在,它能够在无竞争的情况下避免不必要的锁开销。
    • ReentrantReadWriteLock:在读操作远多于写操作的场景中表现良好,但写锁的饥饿问题和锁降级操作可能影响其性能。
  3. 实现机制
    • StampedLock:并非基于AQS(AbstractQueuedSynchronizer)实现,而是使用了自己的同步等待队列和状态设计。其状态为一个long型变量,与ReentrantReadWriteLock的设计不同。
    • ReentrantReadWriteLock:基于AQS实现,通过内部维护的读写锁来实现多线程间的同步。
  4. 使用场景
    • StampedLock:更适合于读多写少且对性能要求较高的场景,尤其是当数据争用不严重时。它能够有效减少锁的竞争,提高系统的吞吐量。
    • ReentrantReadWriteLock:适用于需要重入锁或需要在写操作后降级为读锁的场景。它提供了更严格的访问控制,但可能在某些情况下牺牲了一定的性能。
  5. 锁的获取与释放
    • StampedLock:在获取锁时会返回一个戳记(stamp),用于后续的锁释放或转换。这个戳记代表了锁的状态,有助于在释放锁时验证数据的一致性。
    • ReentrantReadWriteLock:没有戳记的概念,锁的获取和释放相对简单直接。

综上所述,StampedLock和ReentrantReadWriteLock各有其特点和适用场景。在选择使用哪种锁时,应根据具体的应用需求和性能要求来做出决策。

点赞 -收藏 -关注
有问题在评论区或者私信我-收到会在第一时间回复
http://www.yayakq.cn/news/435795/

相关文章:

  • 四网合一网站建设网站安全加固
  • 北京朝阳网站设计做网站怎么赚钱
  • 个人简历免费制作网站顶尖网站建设公司
  • 织梦网站定制wordpress修改评论
  • 翠竹营销网站设计国外网站空间 月付
  • 站长论坛 激活网站展厅设计要考虑哪些方面
  • 网站推广策划案哪里有济南 网站优化
  • 专业平台建设网站关了吗淘宝电商运营
  • 用dw代码做美食网站宁波妇科医生推荐
  • wordpress会员注册seo课程培训中心
  • 网站后台登陆网址是多少一个软件开发流程
  • 静态网站做等级保护内蒙古建设住房与城乡厅官方网站
  • 网站建设好的公司哪家好自己在线制作logo免费u钙网
  • 网站开发培训光山天河网站建设哪家好
  • 东莞长安网站优化公司培训课程有哪些
  • 河口区建设工程招标网站推广优化
  • 用手机做自己的网站wordpress微论坛主题
  • dedecms 网站重复文章网站做推广有用吗
  • 蚌埠做网站的公司哪家好怎么做企业网站
  • wordpress的安装wordpress主题seo
  • 电子商务网站的建设费用网站建设不完整什么意思
  • 门户网站建设自查报告专做商业平台网站
  • 做同城服务网站比较成功的网站长沙网站seo厂家
  • 美术馆网站的建设流程灵当crm客户管理系统
  • 网站建设百度认证图片wordpress 电脑微信登陆不了
  • 搭建邮箱网站wordpress本地访问满
  • 惠州做网站建设价格系统官网网站模板下载
  • 企业网站名备案网站信息核验单
  • 网站备案网站建设 青海
  • 购物网站界面 管理员需求分析重庆网站建设机构