【问题标题】:What is the best way to atomic-replace all contents in List in Java?在 Java 中原子替换 List 中所有内容的最佳方法是什么?
【发布时间】:2014-03-21 13:29:07
【问题描述】:

假设我有一个List,其角色为缓存。大多数时间列表是只读每隔几秒购买一次我想做原子替换所有列表内容。

在原子中,我的意思是我不想让缓存客户端在例如clear()addAll() 之间命中读取。

使用什么列表实现以及如何执行替换以获得最佳性能?

替换列表内容好还是替换引用值本身好?

【问题讨论】:

  • 我更喜欢您的第二个选项,您可以在更短的时间内锁定参考。

标签: java list caching collections concurrency


【解决方案1】:

Java 有一个ReadWriteLock,它支持并发读取和独占写入。正如 JavaDoc 中所提到的,如果更新发生的频率不是很高并且读取发生的频率很高,那么它是一个不错的选择。您的作家更新List 的速度越快,您获得的性能就越好。

readLock() 方法必须由读者调用,而 writeLock() 必须由作者调用。然后你必须在获得的 Lock 上调用 lock()。如果可用,踏板会继续工作,否则会阻塞,直到锁可用。

在构造ReadWriteLock 时使用公平性,以使读取器和写入器线程能够按照它们请求的顺序获取它们的锁。否则某些线程可能会永远等待(在最坏的情况下)。

ReadWriteLock 的好处是许多读者可以共享同一个锁而没有获得它,这是一个扩展操作。这种好处只有在阅读和写作之间的比例非常有利于阅读的情况下才能观察到。

【讨论】:

  • 会比仅仅将 volatile 引用更改为新的列表对象更快吗?
  • Java volatile 关键字仅确保读取相同共享数据的许多线程必须更新该数据的任何本地缓存值。据我所知,它不提供任何同步机制。也许你有兴趣阅读这篇关于 volatile 关键字的example,我认为这是一个非常好的关键字。
【解决方案2】:

如果你真的想使用List<> 类型作为缓存,你可以使用如下锁:

private static final Objet cacheLock  = new Object();


 public void updateListCache()
 {
    synchronized(lock)
    {
       //update your list cache
    }

 }

你的读操作也需要实现这个锁,否则用处不大。

但出于缓存目的,我个人会选择ConcurrentHashMap,因为它是线程安全的。

【讨论】:

    猜你喜欢
    • 2010-09-28
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多