JUC之读写锁:ReadWriteLock

为什么会存在读写锁呢?
1、因为synchronized粒度太大了,并不适合我们,可重入锁的粒度相较于读锁(共享锁)也较大,我们需要粒度小的锁。
2、大部分场景下,读不需要加锁,而写需要加锁,因为写入不加锁有可能出现写入覆盖和信息不一致的情况,并且大部分的读需求粒度更小的锁,这样会占用更少的资源。

独占锁(写锁)—次只能被一个线程占有
共享锁(读锁)多个线程可以同时占有

在这里插入图片描述
这里先不加锁

import java.util.HashMap;
import java.util.Map;

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 1; i <= 5; i++) {
            final int num = i;
            new Thread(() -> {
            myCache.set(num+"",num+"");
            }).start();
        }

        for (int i = 1; i <= 5; i++) {
            final int num = i;
            new Thread(() -> {
                myCache.get(num+"");
            }).start();
        }

    }
}
class MyCache{
        private volatile Map<String,String> map=new HashMap();
        public void set(String key,String value){
            System.out.println("准备存入键中:"+key);
            map.put(key,value);
            System.out.println(key+"存入了");
        }
        public void get(String key){
            System.out.println("获取到了键"+key);
            String value = map.get(key);
            System.out.println("取到了键"+key+"里的值:"+value);
        }
}


会发现set过程中会被其他线程插队:

准备存入键中:1
准备存入键中:2
2存入了
1存入了
准备存入键中:3
3存入了
准备存入键中:5
5存入了
准备存入键中:4
获取到了键2
取到了键2里的值:2
获取到了键4
取到了键4里的值:null
获取到了键1
取到了键1里的值:1
4存入了
获取到了键3
获取到了键5
取到了键5里的值:5
取到了键3里的值:3

如果我们在写入的时候不想要其他线程插队,那么就要引入读写锁:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 1; i <= 5; i++) {
            final int num = i;
            new Thread(() -> {
            myCache.set(num+"",num+"");
            }).start();
        }

        for (int i = 1; i <= 5; i++) {
            final int num = i;
            new Thread(() -> {
                myCache.get(num+"");
            }).start();
        }

    }
}
class MyCache{
        private volatile Map<String,String> map=new HashMap();
        private ReadWriteLock lock=new ReentrantReadWriteLock();

        public void set(String key,String value){
                lock.writeLock().lock();

            try {
                System.out.println("准备存入键中:"+key);
                map.put(key,value);
                System.out.println(key+"存入了");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.writeLock().unlock();
            }
        }
        public void get(String key){
            lock.readLock().lock();
            try {
                System.out.println("获取到了键"+key);
                String value = map.get(key);
                System.out.println("取到了键"+key+"里的值:"+value);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.readLock().unlock();
            }
        }
}


结果:

准备存入键中:1
1存入了
准备存入键中:2
2存入了
准备存入键中:3
3存入了
准备存入键中:4
4存入了
准备存入键中:5
5存入了
获取到了键1
取到了键1里的值:1
获取到了键2
取到了键2里的值:2
获取到了键5
获取到了键4
取到了键4里的值:4
获取到了键3
取到了键3里的值:3
取到了键5里的值:5

Process finished with exit code 0

写锁由于是独占锁,所以在输出完毕前并不会被抢占。但读锁是共享锁,所以并不会被锁影响,还是会继续输出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值