ReentrantReadWriteLock、StampedLock读写锁

1.ReentrantReadWriteLock

当读取操作远远高于写操作时,这时候使用读写锁让读-读可以并发(即然多个线程的读取是可以并行的),提高性能。

类似于数据库中的 select ... from ... lock in share mode

提供一个数据容器类,内部分别使用读锁保护数据的read()方法,写锁保护数据的write()方法

注意事项:

1.读锁不支持条件变量,写锁支持

2.重入时升级不支持,即同一个线程第一次获取的是读锁,然后又去获取写锁,会导致获取写锁永久等待(阻塞住了)

如下:

3.重入时支持降级:即先获取写锁,然后获取读锁。

扫描二维码关注公众号,回复: 14734401 查看本文章

2.StampedLock

该类自JDK8加入,是为了进一步优化读性能,它的特点是在使用读锁、写锁时都必须配合戳使用

加解读锁

long stamp = lock.readLock();
lock.unlockRead(stamp);

加解写锁

long stamp = lock.writeLock();
lock.unlockWrite(stamp);

乐观读,StampedLock支持tryOptimisticRead()方法(乐观读),读取完毕后需要做一次戳校验,如果校验通过,表示这期间确实没有写操作,数据可以安全使用,如果校验没有通过,需要重新获取读锁,保证数据安全。

long stamp = lock.tryOptimisticRead();
//验戳
if(!lock.validate(stamp)){
//锁升级
}

StampedLock的乐观读和普通的读锁的区别是:普通的读锁在多个线程同时读的时候,所有的写操作会被阻塞,而 StampedLock 提供的乐观读,是允许线程获取写锁的,也就是说不是所有的写操作都被阻塞,也就是说乐观读其实是无锁的。那具体要如何使用呢?我们来看一个简单的例子

public class DataContainerStamped {
    private int data;
    private final StampedLock lock = new StampedLock();

    public DataContainerStamped(int data) {
        this.data = data;
    }

    public int read(int readTime) throws InterruptedException {
        long stamp = lock.tryOptimisticRead();
        System.out.println("optimistic read locking ..."+stamp);
        Thread.sleep(readTime);
        //戳没有改变,即这段时间内没有其他线程进行写操作
        if (lock.validate(stamp)){
            System.out.println("read finish... "+stamp);
            return data;
        }
        //锁升级 - 读锁
        System.out.println("updating to read lock... "+stamp);
        try{
            stamp = lock.readLock();
            System.out.println("read lock... "+stamp);
            Thread.sleep(readTime);
            System.out.println("read finish... "+stamp);
            return data;
        }finally {
            System.out.println("read unlock "+stamp);
            //释放悲观读锁
            lock.unlockRead(stamp);
        }
    }

    public void write(int newData) throws InterruptedException{
        long stamp = lock.writeLock();
        System.out.println("write lock... "+stamp);
        try {
            Thread.sleep(2000);
            this.data = newData;
        } finally {
            System.out.println("write lock... "+stamp);
            lock.unlockWrite(stamp);
        }
    }

}

比读写锁(ReadWriteLock)更快的锁(StampedLock)_weihubeats的博客-CSDN博客_比读写锁更快的锁

注意

* StampedLock 不支持条件变量(ReentrantReadWriteLock写锁支持)

* StampedLock 不支持可重入(ReentrantReadWriteLock支持降级不支持升级)

猜你喜欢

转载自blog.csdn.net/weixin_54401017/article/details/127185585