ReadWriteLock原理

读写锁

读读共享, 读写和写写都互斥.因为锁粒度更小, 性能比ReentrantLock好.

读写锁应用场景

  1. 读多写少
  2. 缓存

ReentrantReadWriteLock

ReentrantReadWriteLock是基于aqs实现的一把读写锁

使用示例:


@Slf4j
public class ReadWriteDemo {

    private static int count;

    private static ReentrantReadWriteLock.ReadLock readLock;

    private static ReentrantReadWriteLock.WriteLock writeLock;

    static {
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        readLock = readWriteLock.readLock();
        writeLock = readWriteLock.writeLock();
    }

    public static int read() {
        readLock.lock();
        log.info("获取读锁");
        try {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return count;
        } finally {
            readLock.unlock();
            log.info("释放读锁");
        }
    }

    public static void write() {
        writeLock.lock();
        log.info("获取写锁");
        try {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            count++;
        } finally {
            writeLock.unlock();
            log.info("释放写锁");
        }
    }

    public static void main(String[] args) {
        new Thread(ReadWriteDemo::read).start();
        new Thread(ReadWriteDemo::read).start();
        new Thread(ReadWriteDemo::write).start();
        new Thread(ReadWriteDemo::write).start();
    }
}

注意事项:

  1. 读锁是必要的, 为了保证数据可见性
  2. 重入锁可降级, 不可升级,. 也就是已经获取写锁的线程, 可以重入获取读锁, 反之不行

StampedLock

乐观读, 比ReentrantReadWriteLock读写锁性能更高, 没有写操作时不加锁.

不支持可重入, 不支持公平锁, 适合读多写少.

示例:

@Slf4j
public class StampedLockDemo {

    private static StampedLock stampedLock = new StampedLock();

    private static int x;

    private static int readX() {
        // 获取一个乐观读, 无锁操作
        long stamp = stampedLock.tryOptimisticRead();
        // 业务操作
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.error("error", e);
        }
        // 判断是否有写入
        if (!stampedLock.validate(stamp)) {
            // 如果有写入, 加读锁
            stamp = stampedLock.readLock();
            log.info("获取读锁");
            try {
                return x;
            } finally {
                stampedLock.unlockRead(stamp);
                log.info("释放读锁");
            }
        } else {
            log.info("无改动, 不用加锁");
        }
        return x;
    }

    private static void write(int val) {
        long stamp = stampedLock.writeLock();
        log.info("获取写锁");
        try {
            x = val;
        } finally {
            stampedLock.unlockWrite(stamp);
            log.info("释放写锁");
        }
    }

    public static void main(String[] args) {
        new Thread(() -> readX()).start();
//        new Thread(() -> readX()).start();
        new Thread(() -> write(19)).start();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值