【Java基础】线程笔记——显式锁StampedLock

首先了解悲观锁和乐观锁概念

悲观锁:假设会发生并发冲突,屏蔽一切可能违反数据完整性的操作
读取悲观锁:在读取之前先判断以下,数据有无修改。
乐观锁:假设不会发生并发冲突,只在提交操作前检查是否违反数据完整性的操作
读取乐观锁:在读取之前不需要判断数据是否被修改,只需读取自己的数据

StampedLock

StampedLock是基于能力的锁,很好的实现悲观锁和乐观锁的逻辑。
使用三种模式控制读-写访问
StampedLock的状态包含版本和模式,获取锁方法根据锁状态返回一个表示控制表示的标识(stamp)
“try”版本的方法返回特殊值”0”表示获取失败
锁释放需要一个标识作为参数。如果不符合锁状态则失败

3种模式

  1. writeLock可能阻塞等待独占访问,返回一个标志,用在unlockWrite释放锁。也提供无时间或者带时间版本的tryWriteLock方法
    当锁以写模式持有时,没有读锁可获取。所有乐观性读确认失败

  2. readLock阻塞等待非独占访问,用在unlockRead释放锁。也提供无时间或者带时间版本的tryWriteLock方法

  3. 乐观读

    只有在锁没有以写模式持有时,tryOptimisticRcad()返回一个非0标识。
    如果锁自给定标识没有写模式持有,validate()返回true(可认为极弱版本的读锁,可在任意时间被写入打破)
    在短的只读代码使用乐观模式可以减少竞争,提高吞吐。

    StampedLock

    利用Lock机制+Stamp标记状态。实现锁与锁之间乐观和悲观

Java Doc Example

public class StampedLockDemo {

    private double x;
    private double y;

    final StampedLock lock = new StampedLock();

    //一个简单的写模式例子
    public void move(double deltaX, double deltaY){
        //标志
        long stamp = lock.writeLock();

        try {
            x += deltaX;
            y += deltaY;
        } finally{
            lock.unlockWrite(stamp);
        }
        System.out.println("写入...x = " + x + " " + "y = " + y);
    }

    //乐观读锁
    public double distanceFromOrigin(){
        long stamp = lock.tryOptimisticRead();
        double currentX = x;
        double currentY = y;
        System.out.println("读取...x = " + x + " " + "y = " + y);
        //检查是否有写锁发生
        if(!lock.validate(stamp)){
            stamp = lock.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally{
                lock.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }

    //悲观锁
    public void moveIfAtOrigin(double newX, double newY){
        long readStamp = lock.readLock();
        try{
            //检查状态是否符合
            while(x == 10.0 && y == 10.0){
                //将读锁转为写锁
                long writeStamp = lock.tryConvertToWriteLock(readStamp);
                //确认写锁是否成功
                if(writeStamp != 0L){
                    readStamp = writeStamp;//成功则替换
                    x = newX;
                    y = newY;
                    break;
                }else{
                    lock.unlockRead(readStamp);
                    readStamp = lock.writeLock();
                }
            }
            System.out.println("读锁变为写锁后:x = "+x + " y = " + y);
        }finally{
            lock.unlock(readStamp);
        }
    }
}

运行

public static void main(String[] args) {

        StampedLockDemo demo = new StampedLockDemo();
        demo.move(10,10);
        System.out.println(demo.distanceFromOrigin());
        demo.moveIfAtOrigin(100,200);
}

console

写入...x = 10.0 y = 10.0
读取...x = 10.0 y = 10.0
14.142135623730951
读锁变为写锁后:x = 100.0 y = 200.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值