编程思想 Copy-on-Write

本文将介绍 Copy-on-Write 模式。

一、Copy-on-Write

Copy-on-write (sometimes referred to as “COW”) is an optimization strategy used in computer programming. The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, they can all be given pointers to the same resource. This function can be maintained until a caller tries to modify its “copy” of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else. All of this happens transparently to the callers. The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.

COW,Copy On Write,写时拷贝,即 “读时不拷贝,写时才拷贝”。

COW 的主要思想是:如果有多个调用者同时请求相同资源,他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的。

COW 的主要优点是:如果调用者没有修改该资源,就不会有副本被创建,因此可以共享资源,避免性能损耗。

二、Copy-on-Write 在 JUC 中的应用

Copy-on-Write 在 JUC 中的应用侧重于 “写时拷贝”。

其基本思想是:在写时,拷贝资源后再做修改。

CopyOnWriteArrayList 和 CopyOnWriteArraySet 便是 Copy-on-Write 在 JUC 中的应用。

Copy-on-Write 在 JUC 中的应用将会由于数据的复制导致额外的内存开销,因此更适用于 “读多写少” 的场景。

三、Copy-on-Write 在操作系统的应用

Copy-on-Write 在操作系统中的应用侧重于 “读时不拷贝”。其基本思想是:如果希望复制一个对象,可以先不进行复制,而是创建一个新指针并指向原对象,当需要进行写入操作时才真正复制对象。

操作系统提供 fork() 方法,用于创建一个与指定进程(父进程)相同的进程(子进程),

  • 在不使用 Copy-on-Write 机制的操作系统中,需要复制父进程的所有内存,以供子进程使用,这将会非常耗时
  • 在 Linux 中,fork() 方法会先拷贝父进程的内存信息,让父子进程共用内存,从而更快、更省性能、更省空间地创建出子进程。只有当父子进程发生写操作,需要改变内存数据时,才会进行真正的内存复制。

在操作系统中使用 Copy-on-Write 机制能够减少性能开销。

需要注意的是,fork() 中的 “页表拷贝” 操作会阻塞主线程,且主线程的内存越大阻塞时间越长。

参考

  • Java 并发编程实战