读写分离优缺点_怎么实现读写分离(写时复制)的Map?

01.为什么还需要使用读写分离的Map?

首先我们先介绍一下常用的Map

  1. 线程不安全
  • HashMap : 非线程安全,即任一时刻可以由多个线程同时写HashMap,可能会导致数据不一致。
  • LinkedListHashMap: 非线程安全,保证 加入的顺序是怎么,循环出来就是什么顺序。可以理解为维护了元素次序的HashMap。
  • TreeMap:有序的集合,可以实现自定义排序。

2.线程安全

    • HashTable : 线程安全,但是读和写都需要加锁,性能比较低。
    • ConcurrentHashMap: 采用分段锁实现,但是同一段的写和读也是互斥的,所以性能稍微低

那么如何实现一个缓存呢,可以进行并发的读和写的,从上面介绍类看,

无论是HashTable 还是 ConcurrentHashMap 都会遇到读加锁的情况,所以不太适合这种场景。

那么我们下面实现可以进行读写分离的Map,即写加锁,读不加锁。

02. CopyOnWriteMap 的实现

1、实现步骤如下

  1. 定义一个由初始容量的map.并使用volatile 修饰,这个为了保证在多线程环境下可见性。
  2. 定义一个 可重入锁 ReentrantLock
  3. 定义 put 方法,putAll方法,get方法

2、代码实现

b9db4b37947b5e15cc51549f436e8169.png

3、说明

  • put 方法
    • 首先加锁
    • new 一个新的Map,然后把旧的map放进去
    • 在新的Map中添加元素
    • 将旧map 的引用指向 新的 map
    • 释放锁
  • get 方法
    • get 方法不需要获取锁,直接获取即可。

03. 使用场景

假如有下面一个场景,一个比较小的电商网站(商品信息比较少),所以我们可以直接缓存在内存中,

后期添加、删除、更新都会更新内存中的缓存。

实现代码如下:

968836a531ca57b2d11bbc0d426ac88d.png

使用CopOnWriteMap需要的注意事项:

1、尽量批量添加,否则每次添加都会复制一个map容器,可能会造成频繁的GC(垃圾回收)。

2、尽量初始化时指定容量

CopyOnWriteMap 优缺点

  1. 优点
    1. 实现读写分离,读不加锁,写加锁,性能比较高,适合在高并发场景下使用。
    2. 对比HashTable 和 ConcurrentHashMap ,CopyOnWriteMap 优势在于读不加锁。并发高。
  2. 缺点
    1. 内存占用高的问题。
    2. 对写入的数据不能及时读出来

下面说明为什么内存占用高:


     
     
  1. public V put(K key, V value) {
  2. try {
  3. lock. lock();
  4. Map <K,V > newMap = new HashMap <>(map);
  5. V v = newMap.put( key, value);
  6. map = newMap;
  7. return v;
  8. } catch ( Exception e) {
  9. } finally {
  10. lock. unlock();
  11. }
  12. return null;
  13. }

从上面看,put操作首先 创建一个新的map,然后把添加的元素添加到新map中,

最后把旧的 map引用指向新的map内存地址。

示意图如下:

84825a77c8e81f7e2ad610a365db8c99.png

执行 map = newMap; 代码后:

a31482d21420d82af4bf8dd202de4a01.png

上面旧的map引用虽然指向了新的Map,但是旧的Map如果回收不及时,会造成内存溢出。

为什么要使用COW ?

java util 下的集合类都不能应付并发的修改和添加,比如在迭代集合的时候对此集合进行删除,

则会出现 ConcurrentModificationException异常,或者 多个线程并发的添加,

会出现 上一个添加的值被下一个值覆盖。

为了应付并发的修改,有以下两种办法

1、写时复制

2、线程安全的容器

比如: ArrayList --> CopyOnWriteList

HashSet --> CopyOnWriteSet

HashMap --> ConcurrentHashMap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值