并发遍历实现线程安全遍历

并发集合实现线程安全的遍历通常有两种方式:

一是对遍历对象的快照进行遍历。二是对遍历对象进行准实时的遍历。

快照是在Iterator实例被创建的那一刻待遍历对象内部结构的一个吟诗副本(对象),它反映了待遍历集合的某一时刻(即Iterator实例被创建的那一刻)的状态(不包括集合元素的状态)。由于对同一个并发集合进行遍历操作的每个线程会得到各自的一份快照,因此快照相当于这些线程的线程特有对象。所以,这种方式下进行遍历操作的线程无须加锁就可以实现线程安全。另一方面,快照是只读的,这种Iterator实例是不支持remove方法的。这种方式的优点是遍历操作和更新操作之间互不影响;缺点是当被遍历的集合比较大时,创建快照的直接或者是间接开销会比较大。CopyOnWriteArrayListCopyOnWriteArraySet就是使用这种遍历方法。

准实时是指遍历操作不是针对待遍历对象的副本进行的,但又不借助锁来保障线程安全,从而使得遍历操作可以与更新操作并发进行。并且,遍历过程中其他线程对被遍历对象的内部结构的更新(比如删除元素)可能会(也可能不会)被反映出来。这种遍历方式所返回的Iterator实例可以支持remove方法。ConcurrentLinkedQueueConcurrentHashMap等并发集合就采用这种遍历方式。由于Iterator是被设计用来一次只被一个线程使用的,因此如果有多个线程需要进行遍历操作,那么这些线程之间是不适宜共享同一个Iterator实例的。

你可能感兴趣的:(并发遍历实现线程安全遍历)