jdk8 新特性之StampedLock锁

参考《java并发编程之美》

 

对于java8新增的特性来看,主要是

1,接口方法可以提供默认的实现,

2,及函数式编程,

目前大部分说到java8 新特性都会想到以上两点,却很少人知道java8 还新增了其他的新特性,今天来聊聊java8 新增的锁的新特性,StampedLock。

StampedLock是并发包里面jdk8版本新增的一个锁,该锁提供了3种模式的读写控制,当调用该锁的一系列函数时,会返回一个long类型的值,这个变量值我们称之为(stamp),这个stamp代表了锁的状态。其中try系列获取锁的方法,当获取锁失败之后,会返回为0的stamp值。当调用释放锁和转换锁的方法时需要传入获取锁时返回的stamp值。

接下来分别介绍StampedLock的三种读写模式的锁。

  • 写锁 writeLock

该锁是一个排它锁还在独占锁,无论哪个时候只能有一个线程获取到锁。排它锁的特性和概念在这里就不介绍了,不清楚的可以上网查查。我们都知道ReentrantReadWriteLockd的写锁就是一个排它锁,这里呢咱们的这个写锁类似于ReentrantReadWriteLockd的写锁,不同的是怎么的写锁是不可重入锁。也就是当前没有线程持有读锁或者写锁时才可以获取到该锁。

在请求该锁成功后悔返回一个stamp值用来表示该锁的版本,当释放该锁时需要调用unlockWrite方法并传递获取锁时获取到的stamp值。并且它提供了非阻塞的tryWriteLock方法。

  • 悲观读锁ReadLock

是一个共享锁,在没有线程获取独占写锁的情况下,多个线程可以同时获取该锁。如果已经有线程占有写锁,则其他线程获取该锁都会被阻塞,这类似于ReentrantReadWriteLock的读锁,但是这里的读锁是不可重入锁。

这里说悲观就知道,不言而喻,我们都知道悲观锁(不管是写还是读操作,都认为会改变到数据,所以在操作之前都会对数据加上锁),这里也是这样的,会悲观的认为其他线程会修改数据,所以需要对数据加锁。

在请求该锁成功后会返回一个stamp值来标识该锁的版本,释放锁的时候需要调用unlockRead方法,并传递stamp值。并且它提供了非阻塞的tryReadLock方法。

  • 乐观读锁tryOptimisticRead

它是相对于悲观锁来说,在操作数据之前没有通过CAS设置锁的状态,仅仅通过位运算测试。如果当前没有线程获取写锁,则简单返回一个非0的stamp版本信息,获取该值之后,在之后的具体操作数据前还需要调用validata方法校验该stamp值是否已经可用(获取该stamp值后在具体操作数据之前这段期间有没有其他线程获取是否占有写锁,如果是validata会返回0,否则就可以使用该stamp版本来对数据进行操作。),由于没有tryOptimisticRead并没有使用CAS设置锁的状态。所以不需要显示的释放锁。该锁适合在读多写少的场景。

在保证数据一致上需要复制一份要操作的变量到方法栈。

StampedLock 支持这三种锁在 定条件下进行相互转换
例如 long tryConvertTo WriteLock(long tamp 期望把 tamp 标示的锁升级为写锁 这个函数会在下面
种情况下返回 个有效的 stamp 也就是晋升写锁成功)

1.当前锁已经是写模式了,

2.当前锁处于读模式,并且没有其他线程是读锁模式

3.当前处于乐观锁模式,并且当前写锁可用。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章