ReentrantLock、ReentrantReadWriteLock、StampedLock

文章探讨了Java并发中的ReentrantReadWriteLock读写锁,强调了锁降级的概念和重要性,指出读写锁的不可锁升级和互斥特性。同时,介绍了StampedLock作为解决锁饥饿问题的优化方案,其乐观读锁模式允许在读取过程中容忍写入,提高并发性能。最后,提到了StampedLock的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、大厂面试题

二、请你简单聊聊ReentrantReadWriteLock 读写锁

1.是什么

①:读写锁说明

②:演变


③:【读写锁】意义和特点

2.特点

ReentrantReadWriteLock锁降级

降级

锁降级是为了让当前线程感知到数据的变化,目的是为了保证数据的可见性

不可锁升级


写锁和读锁是互斥的


读写锁之读写规矩,解释为什么要锁降级?



三、邮戳锁StampedLock

1.是什么

2.它是由锁饥饿问题引出

①:锁饥饿问题

②:如何缓解锁饥饿问题


③:StampedLock类的乐观读锁闪亮登场

3.StampedLock的特点


4. 乐观读模式

读的时候不允许获取写锁的介入

public class StampedLockDemo {
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public void write() {
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName() + " 写线程准备修改");
        try {
            number = number + 13;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName() + " 写线程结束修改");
    }

    //悲观读,读没有完成时候写锁无法获得锁
    public void read() {
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName() + "  come in readLock code lock,4 seconds continue ...");
        //暂停4秒钟
        for (int i = 0; i < 4; i++) {
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(Thread.currentThread().getName() + " 正在读取中 ...");
        }

        try {
            int result = number;
            System.out.println(Thread.currentThread().getName() + " 获得成员变量值result=" + result);
            System.out.println("写线程没有修改成功,读锁时候写锁无法介入,传统的读写互斥");
        } finally {
            stampedLock.unlockRead(stamp);
        }
    }


    public static void main(String[] args) {
        StampedLockDemo resource = new StampedLockDemo();
        new Thread(() -> {
            resource.read();
        }, "readThread").start();
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "  . . .come in");
            resource.write();
        }, "writeThread").start();
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println(Thread.currentThread().getName() + " number:" + number);
    }
}

readThread  come in readLock code lock,4 seconds continue ...
readThread 正在读取中 ...
writeThread  . . .come in
readThread 正在读取中 ...
readThread 正在读取中 ...
readThread 正在读取中 ...
readThread 获得成员变量值result=37
写线程没有修改成功,读锁时候写锁无法介入,传统的读写互斥
writeThread 写线程准备修改
writeThread 写线程结束修改
main number:50

public class StampedLockDemo {
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public static void main(String[] args) {
        StampedLockDemo resource = new StampedLockDemo();
        new Thread(() -> {
            resource.tryOptimisticRead();
        }, "readThread").start();
        //暂停2秒钟线程,读过程中可以写介入 演示
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "  . . .come in");
            resource.write();
        }, "writeThread").start();
    }

    public void write() {
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName() + " 写线程准备修改");
        try {
            number = number + 13;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName() + " 写线程结束修改");
    }

    //悲观读,读没有完成时候写锁无法获得锁
    public void read() {
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName() + "  come in readLock code lock,4 seconds continue ...");
        //暂停4秒钟
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 正在读取中 ...");
        }

        try {
            int result = number;
            System.out.println(Thread.currentThread().getName() + " 获得成员变量值result=" + result);
            System.out.println("写线程没有修改成功,读锁时候写锁无法介入,传统的读写互斥");
        } finally {
            stampedLock.unlockRead(stamp);
        }
    }

    //乐观读,读的过程中也允许写锁介入
    public void tryOptimisticRead() {
        long stamp = stampedLock.tryOptimisticRead();
        int result = number;
        //故意间隔4秒钟,很乐观认为读取中没有其它线程修改过number值,具体靠判断
        System.out.println("4秒前stampedLock.validate方法值(true无修改,false有修改) " + stampedLock.validate(stamp));
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 正在读取..." + i + "秒后stampedLock.validate方法值(true无修改,false有修改) " + stampedLock.validate(stamp));
        }

        if (!stampedLock.validate(stamp)) {
            System.out.println("有人修改过---有写操作");
            stamp = stampedLock.readLock();
            try {
                System.out.println("从乐观读 升级为 悲观读");
                result = number;
                System.out.println("重新悲观读后result:" + result);
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        System.out.println(Thread.currentThread().getName() + " finally value:" + result);
    }

}

4秒前stampedLock.validate方法值(true无修改,false有修改) true
readThread 正在读取...0秒后stampedLock.validate方法值(true无修改,false有修改) true
readThread 正在读取...1秒后stampedLock.validate方法值(true无修改,false有修改) true
writeThread  . . .come in
writeThread 写线程准备修改
writeThread 写线程结束修改
readThread 正在读取...2秒后stampedLock.validate方法值(true无修改,false有修改) false
readThread 正在读取...3秒后stampedLock.validate方法值(true无修改,false有修改) false
有人修改过---有写操作
从乐观读 升级为 悲观读
重新悲观读后result:50
readThread finally value:50


5.StampedLock的缺点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值