读写锁以及手写实现

 
读写锁
Java内置了读写锁工具类,方便开发人员针对“读多写少”的场景提升加锁的性能。

为什么需要读写锁?
synchronized和ReentrantLock都属于排他锁,存在明显的性能问题:读读互斥。
当某一个线程获取锁时,其他线程全部阻塞,性能不高。

读写锁可以实现:读读不互斥,仅读写、写写互斥。

对于“读多写少”的场景,允许多个读线程同时操作资源,可以大大提升应用性能。

功能定义
加读锁时,允许其他线程继续加读锁,写锁会被阻塞。
加写锁时,其他线程不管加读锁还是写锁都会被阻塞。

ReadWriteLock接口
ReadWriteLock维护了一个读锁和一个写锁。

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();

使用示例
使用其子类ReentrantReadWriteLock即可。

/**
 * @Author: JimH
 * @Date: 2020/02/16 14:30
 * @Description: ReentrantReadWriteLock例子
 */
public class ReadWriteLockDemo {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    int index = 0;

    void writeFunc(){
        reentrantReadWriteLock.writeLock().lock();
        SleepUtil.sleep(1000);
        System.out.println(++index);
        reentrantReadWriteLock.writeLock().unlock();
    }

    void readFunc(){
        reentrantReadWriteLock.readLock().lock();
        SleepUtil.sleep(3000);
        System.out.println(index);
        reentrantReadWriteLock.readLock().unlock();
    }

    public static void main(String[] args) {
        ReadWriteLockDemo demo = new ReadWriteLockDemo();
        //先加读锁,3s后读锁释放,写锁才能竞争成功
        demo.readFunc();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                demo.writeFunc();
            }).start();
        }
    }

自己实现读写锁
手痒痒,现在看到啥好玩的都想自己手写实现一遍,以便更好的理解。

笔者浅见,可能存在bug,望各位大佬指出。

/**
 * @Author: JimH
 * @Date: 2020/02/16 20:40
 * @Description: 自己实现Java读写锁(不考虑锁的重入)
 */
public class MyReadWriteLock {
    private final ReadLock readLock = new ReadLock();
    private final WriteLock writeLock = new WriteLock();

    //读锁队列
    private ConcurrentLinkedQueue<Thread> readQueue = new ConcurrentLinkedQueue<>();
    //读锁等待队列
    private ConcurrentLinkedQueue<Thread> readWaitQueue = new ConcurrentLinkedQueue<>();

    //当前写锁线程
    private AtomicReference<Thread> currentWrite = new AtomicReference<>();
    //写锁等待队列
    private ConcurrentLinkedQueue<Thread> writeWaitQueue = new ConcurrentLinkedQueue<>();

    //获取读锁
    public ReadLock readLock(){
        return readLock;
    }

    //获取写锁
    public WriteLock writeLock(){
        return writeLock;
    }


    //读锁
    class ReadLock{
        //内部锁标记
        private AtomicBoolean innerLock = new AtomicBoolean(false);

        void lock(){
            //SleepUtil.sleep(10);
            while (!innerLock.compareAndSet(false, true)) {
                //Thread.yield();
                SleepUtil.sleep(1);
            }
            //当前有写锁或写锁等待队列不为空,优先处理写锁
            if (currentWrite.get() != null || !writeWaitQueue.isEmpty()) {
                readWaitQueue.add(Thread.currentThread());
                LockSupport.park();
            }
            //读锁竞争成功
            readQueue.add(Thread.currentThread());
            innerLock.set(false);
            System.out.println("read lock");
        }

        void unlock(){
            readQueue.remove(Thread.currentThread());
            innerLock.set(false);
            if (!readWaitQueue.isEmpty()) {
                //读锁等待队列不为空,唤醒
                LockSupport.unpark(readWaitQueue.poll());
            } else if (readQueue.isEmpty() && readWaitQueue.isEmpty()) {
                //读锁全部释放,且没有读锁等待,唤醒写锁等待队列
                LockSupport.unpark(writeWaitQueue.poll());
            }
            System.out.println("read unlock");
        }
    }

    //写锁
    class WriteLock{
        //内部锁标记
        private AtomicBoolean innerLock = new AtomicBoolean(false);

        void lock(){
            //SleepUtil.sleep(10);
            while (!innerLock.compareAndSet(false, true)) {
                writeWaitQueue.add(Thread.currentThread());
                LockSupport.park();
            }
            //当前没有读锁和写锁,才能加写锁
            if (readQueue.isEmpty() && currentWrite.get() == null) {
                currentWrite.set(Thread.currentThread());
                System.out.println("write lock");
                return;
            }
            writeWaitQueue.add(Thread.currentThread());
            LockSupport.park();
        }

        void unlock(){
            currentWrite.set(null);
            innerLock.set(false);
            if (!writeWaitQueue.isEmpty()) {
                LockSupport.unpark(writeWaitQueue.poll());
                System.out.println("write unlock");
                return;
            }
            LockSupport.unpark(readWaitQueue.poll());
            System.out.println("write unlock");
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值