死磕并发之ReadWriteLock读写锁的使用

  • 所有读写锁都要遵循以下三条基本原则:
  1. 允许多个线程同时读共享变量。
  2. 只允许一个线程写共享变量。
  3. 如果一个线程正在执行写操作,此时禁止读线程读共享变量。
  • 总结: 读-读可以,读-写互斥,写-写互斥。
  • 注意:写锁可降级为读锁,读锁不能升级为写锁。
  • 简单使用示例
public class ReentranReadWriteLokeDemo<K, V> {

    private final Map<K, V> map = new HashMap<K, V>();

    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    final Lock writeLock = readWriteLock.writeLock();

    final Lock readLock = readWriteLock.readLock();


    public V get(K k) {
        readLock.lock();

        try {
            return map.get(k);
        } finally {
            readLock.unlock();
        }
    }

    public V put(K k, V v) {
        writeLock.lock();

        try {
            return map.put(k, v);
        }finally {
            writeLock.unlock();
        }
    }
}
  • 注意避免锁的升级,此时读锁还未释放,去获取写锁,会导致锁永久等待,最终导致相关线程都被阻塞,永远没有机会呗唤醒。如下示例你可以复制代码测试下,线程会一直等待下去:
public class ReentranReadWriteLokeDemo {


    public static void main(String[] args) {
        ReentranReadWriteLokeTest reentranReadWriteLokeTest = new ReentranReadWriteLokeTest();
        Object value = reentranReadWriteLokeTest.get("one");
        System.out.println(value);
    }

    private static class ReentranReadWriteLokeTest<K, V> {
        private final Map<K, V> map = new HashMap<K, V>();

        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

        final Lock writeLock = readWriteLock.writeLock();

        final Lock readLock = readWriteLock.readLock();

        public V get(K k) {
            readLock.lock();

            try {
                V v = map.get(k);
                if (v == null) {
                    writeLock.lock();
                    try {
                        //执行写操作
                        System.out.println("执行写操作");
                    }finally {
                        writeLock.unlock();
                    }
                }
                return v;
            } finally {
                readLock.unlock();
            }
        }

        public V put(K k, V v) {
            writeLock.lock();

            try {
                return map.put(k, v);
            }finally {
                writeLock.unlock();
            }
        }
    }

}
  • 锁的降级是被允许的,如下代码,获取读锁的时候还持有写锁。
 public static void main(String[] args) {
        ReentranReadWriteLokeTest reentranReadWriteLokeTest = new ReentranReadWriteLokeTest();
        reentranReadWriteLokeTest.put("one", "value");
    }

    private static class ReentranReadWriteLokeTest<K, V> {
        private final Map<K, V> map = new HashMap<K, V>();

        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

        final Lock writeLock = readWriteLock.writeLock();

        final Lock readLock = readWriteLock.readLock();

        public V get(K k) {
            readLock.lock();

            try {
                V v = map.get(k);

                return v;
            } finally {
                readLock.unlock();
            }
        }

        public void put(K k, V v) {
            writeLock.lock();

            try {
                V value = map.put(k, v);
                if (value == null) {
                    readLock.lock();
                    try {
                        System.out.println("添加的value为:"+ map.get(k));
                    }finally {
                        readLock.unlock();
                    }
                }
            }finally {
                writeLock.unlock();
            }
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值