StampedLock

java并发编程之美 学习笔记

StampedLock

StampedLock是jdk8之后新增的一个锁,该锁提供了三种模式的读写控制。
当调用获取锁的函数时,会返回一个long型变量,我们称之为戳记(stamp),这个戳记代表了锁的状态。

  • tryXXXLock:获取锁失败返回的stamp=0.
  • 在释放锁unlock(stamp)需要将获取锁时的stamp传入.

StampedLock提供了三种读写模式的锁:

  • 写锁writeLock: 排他独占锁.(不可重入)
  • 悲观读锁readLock:共享锁(不可重入). 这里说的悲观是指,在操作数据之前会悲观的认为其他线程可能对自己操作的数据进行修改,所以要先对数据加锁,这是在读少写多的情况下的一种考虑。
  • 悲观读锁readLock: 它是相对于悲观来说的,在操作数据之前,并没有通过CAS设置锁的状态。
    • 如果当前线程没有持有写锁,则简单的返回一个非0的stamp
    • 获取stamp之后,在操作具体的数据之前还需要validate(stamp)校验stamp是否依然可用(即在持有锁的时间段内,有没有其他线程持有了写锁),如果有则validate返回0,表示不可用。 否则返回一个非0,表示可用。该锁适用于读多写少的应用场景。

锁转换
StampedLock还支持三种锁在一定情况下互相转换,如tryConvertToWriteLock(stamp),期望把stamp标示的锁升级为写锁,但必须满足如下条件中的一个:

  • 当前锁已经处于写模式
  • 当前锁处于读模式,但是没有其他线程持有读锁。
  • 当前处于乐观读模式,目前当前写锁可用。

public class StampedLockTest {
	//StampedLock 的读写锁都是不可重入锁.
	private StampedLock lock = new StampedLock();
	private double x ,y;

	//写锁
	void move(double deltaX , double deltaY) {
		//获取写锁 --- blocking 直到有可用的写锁
		long stamp = lock.writeLock();
		try{
			x += deltaX;
			y += deltaY;
		} finally {
			lock.unlockWrite(stamp);
		}
	}

	//乐观读锁
	double distanceFromOrigin(){
		//获取乐观锁 --- 立即返回一个状态,非0表示可用;
		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);
	}


	// 使用悲观锁获取读锁,并尝试转换为写锁
	void moveIfOrigin(double newX ,double newY) {
		//获取悲观读锁 --- blocking 直到有可用的读锁
		long stamp = lock.readLock();
		try{
			while( x == 0.0 && y == 0.0){
				//尝试将获取的读锁升级为 写锁
				long ws = lock.tryConvertToWriteLock(stamp);

				//升级成功 ,则 更新戳记,并设置坐标值,然后退出循环
				if(ws != 0 ){
					stamp = ws;
					x = newX;
					y = newY;
					break;
				}else{
					//读锁升级写锁失败则释放读锁,显式获取独占写锁,然后循环重试
					lock.unlockRead(stamp);
					stamp = lock.writeLock();
				}
			}
		} finally {
			lock.unlock(stamp);
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值