Java 并发编程实战
王宝令
资深架构师
72485 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
学习攻略 (1讲)
Java 并发编程实战
15
15
1.0x
00:00/00:00
登录|注册

29 | Copy-on-Write模式:不是延时策略的COW

Router类
RouteTable类
路由表
负载均衡
函数式编程领域
Git背后的设计思想
Docker容器镜像设计
文件系统(Btrfs、aufs)
fork()
CopyOnWriteArraySet
CopyOnWriteArrayList
为什么Java没有提供CopyOnWriteLinkedList
缺点:内存消耗
Copy-on-Write的通用性
Copy-on-Write在Java并发编程领域的知名度
RPC框架
其他领域
操作系统领域
Java领域
课后思考
总结
一个真实案例
应用领域
Copy-on-Write模式
参考文章

该思维导图由 AI 生成,仅供参考

在上一篇文章中我们讲到 Java 里 String 这个类在实现 replace() 方法的时候,并没有更改原字符串里面 value[]数组的内容,而是创建了一个新字符串,这种方法在解决不可变对象的修改问题时经常用到。如果你深入地思考这个方法,你会发现它本质上是一种 Copy-on-Write 方法所谓 Copy-on-Write,经常被缩写为 COW 或者 CoW,顾名思义就是写时复制
不可变对象的写操作往往都是使用 Copy-on-Write 方法解决的,当然 Copy-on-Write 的应用领域并不局限于 Immutability 模式。下面我们先简单介绍一下 Copy-on-Write 的应用领域,让你对它有个更全面的认识。

Copy-on-Write 模式的应用领域

我们前面在《20 | 并发容器:都有哪些“坑”需要我们填?》中介绍过 CopyOnWriteArrayList 和 CopyOnWriteArraySet 这两个 Copy-on-Write 容器,它们背后的设计思想就是 Copy-on-Write;通过 Copy-on-Write 这两个容器实现的读操作是无锁的,由于无锁,所以将读操作的性能发挥到了极致。
除了 Java 这个领域,Copy-on-Write 在操作系统领域也有广泛的应用。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Copy-on-Write模式是一种写时复制的技术,广泛应用于Java中的不可变对象、操作系统、函数式编程等领域。在Java中,Copy-on-Write容器如CopyOnWriteArrayList和CopyOnWriteArraySet实现了无锁的读操作,适用于读多写少的场景。在操作系统领域,Copy-on-Write被用于提升性能,如Linux中的fork()函数以及文件系统Btrfs和aufs。此外,Copy-on-Write还在Docker容器镜像、Git等领域有应用。在函数式编程中,由于基于不可变性,所有修改操作都需要Copy-on-Write来解决。尽管Copy-on-Write会消耗内存,但随着硬件性能的提升和自动垃圾回收算法的成熟,内存消耗已经可以接受。因此,对于写操作较少的场景,可以尝试使用Copy-on-Write来提升性能。文章还提到了一个真实案例,展示了如何使用CopyOnWriteArrayList和CopyOnWriteArraySet来实现路由表,以及如何设计Router类以适应Copy-on-Write模式。总的来说,Copy-on-Write是一种简单且通用的并发解决方案,在多个领域都有着广泛的应用。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(56)

  • 最新
  • 精选
  • 假行僧
    没有提供CopyOnWriteLinkedList是因为linkedlist的数据结构关系分散到每一个节点里面,对每一个节点的修改都存在竟态条件,需要同步才能保证一致性。arraylist就不一样,数组天然的拥有前驱后继的结构关系,对列表的增删,因为是copy on wirte,所以只需要cas操作数组对象就能够保证线程安全,效率上也能接受,更重要的是避免锁竞争带来的上下文切换消耗。有一点需要注意的是CopyOnWriteArrayList在使用上有数据不完整的时间窗口,要不要考虑需要根据具体场景定夺

    作者回复: 👍

    2019-05-05
    15
    131
  • 欢乐小熊
    我对课后的思考是这样的, ArrayList 是用是数组实现的, 在内存上时一块连续的区域, 拷贝时效率比较高, 时间复杂度为 O(1) LinkedList 是链表实现, 其数据是通过指针串联起来的, 并非一块连续的区域, 拷贝时必须要进行遍历操作, 效率比较低, 时间复杂度是 O(n)

    作者回复: 👍

    2019-09-29
    65
  • 夏天
    王老师,问一个单例模式的问题: 在双重检查加锁的单例模式中 需不需要加 volatile 关键字修饰? 自己的理解:是需要。但是我在考虑其中的锁是不是存在happen before规则,不用加volatile也能保证可见性?

    作者回复: 必须加,还有指令重排问题

    2019-05-06
    6
    12
  • 刘infoq
    服务下线了,如果数据不一致,会不会有请求发到下线了的服务器

    作者回复: rpc的客户端和服务提供端会建立一个长连接,定时发心跳,并不完全依赖注册中心的数据。很多rpc的服务端提供了手动下线功能,能解决你说的这个问题

    2019-05-10
    2
    7
  • DFighting
    主要是ArrayList的数据存储是数组,复制可能只需要移动一个内存页或者多个连续的内存空间就可以,而且数组在复制的时候是知道数据集的大小的(动态扩容后也还是数组,只是预先申请了一些未来使用的空间),而LinkdList底层实现为使用Node<?>链表,存储位置分散且大小不可控,如果使用COW可能会适得其反。这应该也是一种用空间换时间的策略吧。这么来看,除非事先限定了数据的存储区域,不然用COW还是数组方便些吧。

    作者回复: 👍

    2019-09-28
    5
  • 与路同飞
    redis中的快照rdb复制也是基于COW的

    作者回复: 👍🏻

    2020-08-14
    4
  • 静水流深
    大师好不容易写了个CopyOnWriteArrayList,再写一个CopyOnWriteLinkedList 他觉得没必要。他也累:)

    作者回复: 😂

    2019-09-26
    3
  • 张三
    上一篇说包装类型、String 是享元模式,这篇说是Copy-on-Write,是两种模式都有吗?

    作者回复: 都有

    2019-05-06
    2
  • 1620
    数组在内存地址是连续的,天然适合copy,链表是分散的。

    作者回复: 👍

    2019-10-15
    1
  • yang
    Sting Long … 居然可以和CoW、Lock联系起来! 跟着老师默默修行! 希望这个专栏永远不要停! 能希望能一直看到老师写的专栏!

    作者回复: 感谢捧场😂

    2019-05-13
    1
收起评论
显示
设置
留言
56
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部