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

    作者回复: 👍

     6
     40
  • Knight²º¹⁸
    2019-05-06
    很多童鞋提到了链表copy的代价,个人觉得这并不是最根本的原因。首先数组无论的新增还是删除copy是避免不了的,因此我们采用copy on write的方式在保证代价相当的前提下保证了并发的安全问题,何乐而不为呢。其次是链表的新增删除压根就不需要复制,就算是在并发场景下采用锁的方式性能损耗都不大,因此也就没必要采用copy的方式了,更何况链表的操作可以采用分段锁、节点锁。所以没有CopyOnWriteLinkedList的主要原因是没有这个必要。
    
     27
  • Corner
    2019-05-04
    数组的拷贝效率应该比链表高,一维数组是连续分配内存的,所以可以直接复制内存块就能完成拷贝。但是链表元素之间是通过引用建立连接的,所以要遍历整个链表才能完成拷贝。
    
     11
  • Sharry
    2019-09-29
    我对课后的思考是这样的, ArrayList 是用是数组实现的, 在内存上时一块连续的区域, 拷贝时效率比较高, 时间复杂度为 O(1)

    LinkedList 是链表实现, 其数据是通过指针串联起来的, 并非一块连续的区域, 拷贝时必须要进行遍历操作, 效率比较低, 时间复杂度是 O(n)

    作者回复: 👍

    
     9
  • nonohony
    2019-05-08
    1.链表本身适合于顺序读和写多的场景,和cop读多写少是违背的。
    2.链表可以锁节点,力度已经很小了。
    3.链表整体复制的性能比数组差太多。
    
     8
  • 夏天
    2019-05-06
    王老师,问一个单例模式的问题: 在双重检查加锁的单例模式中 需不需要加 volatile 关键字修饰? 自己的理解:是需要。但是我在考虑其中的锁是不是存在happen before规则,不用加volatile也能保证可见性?

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

     1
     5
  • ban
    2019-05-04
    一种是通过更新 Router 的一个状态位来标识,如果这样做,那么所有访问该状态位的地方都需要同步访问,这样很影响性能。

    老师好,这句话的意思没怎么看懂,我理解的是route如果下线后更新状态标识,所以每次调用的时候都需要遍历所以route节点,判断每个节点的状态来判断是否下线,所以比较消耗性能的意思吗?所以改成方法二只要下线即删除改route节点,调用的时候不需要判断,只要路由表查到即算都是上线状态。

    
     3
  • 刘鹏
    2019-05-10
    服务下线了,如果数据不一致,会不会有请求发到下线了的服务器

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

    
     2
  • Darren
    2019-05-04
    LinkedList 在复制时,因为其包含前后节点地址,每个节点需要去创建,成本比较高,所以很少或者没有写时复制的Linked 结构吧
    
     2
  • DFighting
    2019-09-28
    主要是ArrayList的数据存储是数组,复制可能只需要移动一个内存页或者多个连续的内存空间就可以,而且数组在复制的时候是知道数据集的大小的(动态扩容后也还是数组,只是预先申请了一些未来使用的空间),而LinkdList底层实现为使用Node<?>链表,存储位置分散且大小不可控,如果使用COW可能会适得其反。这应该也是一种用空间换时间的策略吧。这么来看,除非事先限定了数据的存储区域,不然用COW还是数组方便些吧。

    作者回复: 👍

    
     1
  • 风翱
    2019-06-05
    Copy-on-Write方案是适合读多写少的场景,而LinkedList读取的性能不高,这个应该是没有提供CopyOnWriteLinkedList的主要原因。
    
     1
  • 污名侦探
    2019-05-17
    首先CopyOnWriteLinkedList 可以做分段锁,并且性能很高。其次,复制性能没有数组来的快。
    
     1
  • Vincent
    2019-05-16
    既然读多写少,说明数据结构变更频率很少。那么数组结构适合这个场景,链表是适合写多的场景
    
     1
  • 周治慧
    2019-05-05
    本质就是数组查询块增删慢,链表增删块查询慢。copyandwrite本质就是读多写少即查询多增删少的一个过程所以数组更加合适
    
     1
  • 三年过后
    2020-02-07
    CopyOnWriteLinkedList 显然底层是通过链表实现。链表存储的数据结构是零散的,对于cpu缓存是不友好的,在读多写少的场景下,影响读性能的容器集合,也就没有开放的意义。
    
    
  • Monday
    2019-12-27
    老师好,请问:如案例,正常情况下一个服务提供方应该提供多个接口,是对应多个Router对象?所以一个服务提供方上/下线,应该会循环调用多次add/remove方法?
    
    
  • LoveDlei
    2019-12-20
    COW思想是否可以在多线程下不使用锁保证hashmap线程安全?
    
    
  • 亮
    2019-12-06
    请问下,RouterTable这个类,线程安全吗?感觉remove方法不安全
     1
    
  • Joker
    2019-11-07
    举个例子,如果我们需要进行一次增加,比如在某个位置增加某给值。
    如果是数组的话,我们需要进行数据搬移操作,这无疑需要涉及到整个数组别的位置的操作,如果你是在第一个位置插入,那么就要搬移整个数组了。
    这样一来但凡有插入操作,要么锁住整个数组;要么用COW策略。显然,锁住整个数组,效率就很低了,因为连读都需要获取锁才行。那么就要继续用COW了,起码读的时候不用锁。
    那么如果是链表的话,只需要知道前后节点就行了,不会涉及链表别的位置的节点搬移等操作。所以可以用节点锁,或者分段锁就行了。用不着COW来搞定。
    
    
我们在线,来聊聊吧