jdk8中的StampedeLock锁的使用与原理

1、stampeLock的原理
(1)读锁并不会阻塞写锁:当写的时候读失败了,再重新读。
(2)分为乐观锁和悲观锁,乐观锁时读写不互斥,悲观锁读写互斥。
(3)悲观锁不互斥的原理:获取读写锁的时候都会返回一个标识,然后在 读得时候使用validate(long)方法来判断是否发生了写操作,如果发生 了就再次进行读取。
(4)StampedLock的等待队列与RRW的CLH队列相比,有以下特点:

1、当入队一个线程时,如果队尾是读结点,不会直接链接到队尾,而是链接到该读结点的cowait链中,cowait链本质是一个栈;
2、当入队一个线程时,如果队尾是写结点,则直接链接到队尾;
3、唤醒线程的规则和AQS类似,都是首先唤醒队首结点。区别是StampedLock中,当唤醒的结点是读结点时,会唤醒该读结点的cowait链中的所有读结点(顺序和入栈顺序相反,也就是后进先出)。
4、另外,StampedLock使用时要特别小心,避免锁重入的操作,在使用乐观读锁时也需要遵循相应的调用模板,防止出现数据不一致的问题。
5、详情:https://segmentfault.com/a/1190000015808032?utm_source=tag-newest

2、代码实现demo:

package cn.shiyujun.thread.t3;

import java.util.concurrent.locks.StampedLock;

public class Demo {

    private int balance;

    private  StampedLock lock = new StampedLock();

    /**
     * 在满足一定条件下将读锁转换成写锁
     * @param value
     */
    public void condditionReadWrite(int value){
        //首先判断balance的值是否符合更新的条件
        long stamp = lock.readLock();
        while (balance > 0){
            long writeStamp = lock.tryConvertToWriteLock(stamp);
            if(writeStamp != 0){ //成功转换成为写锁
                stamp = writeStamp;
                balance += value;
                break;
            }else{
                //没有转换成写锁,这里需要首先释放读锁,然后再拿到写锁
                lock.unlockRead(stamp);
                //获取写锁
                stamp = lock.writeLock();
            }
        }
        lock.unlock(stamp);
    }

    /**
     * 乐观锁采用的读操作,读写操作时不互斥
     */
    public void optimisticRead(){
        long stamp = lock.tryOptimisticRead();
        int c = balance;

        //这里可能会出现了写操作,因此要进行判断,如果此时发生了写操作重新则重新读取
        if(!lock.validate(stamp)){
            //要从新读取
            long readStamp = lock.readLock();
            c = balance;
            stamp = readStamp;
            lock.unlockRead(stamp);
        }

        System.out.println("读操作成功,value:"+c);
    }

    /**
     * 悲观锁读,读写互斥,获取读锁失败后
     * 队尾结点如果是写结点,读结点会直接链接到队尾;如果队尾是读结点,则会链接到队尾读结点的cowait链中
     */
    public void read(){
        long stamp = lock.readLock();
        int c = balance;
        //...
        lock.unlockRead(stamp);
        System.out.println("读操作成功,balance:"+balance);
    }

    /**
     * 悲观锁写,读写互斥,获取写锁失败后将写锁加入到链接的队尾
     * @param value
     */
    public void write(int value){
       long stamp = lock.writeLock();
       balance += value;

       lock.unlockWrite(stamp);
        System.out.println("写操作成功,balance:"+balance);
    }

    public static void main(String[] args) {

        Demo demo = new Demo();
        demo.write(2);
        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.write(2);
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.optimisticRead();
            }
        }).start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值