【问题标题】:syncrhonize access on arrayList同步对 arrayList 的访问
【发布时间】:2015-01-03 08:15:52
【问题描述】:

我有一个函数可以插入作为参数传递的arrayList字符串。这个函数可以被不同的线程访问,

public void adding(String newStringForEachInvocation){

             arrayList.add(newStringForEachInvocation);
}

我想同时保留add 方法,我的疑问是,如果两个threads 有两个不同的字符串,它们是否有可能竞争同一个存储桶?

另一种选择是使用 blockingQueue ,但无论如何它可能代表线程竞争同一个存储桶的相互排斥?

【问题讨论】:

  • blockingQueue 被设计成可以处理竞争。如果要模拟比赛场景,则必须手动编写互斥锁和信号量。

标签: java multithreading arraylist


【解决方案1】:

是的,ArrayList 不是线程安全的,因此,如果它被多个线程访问(显式地,和/或使用Collections.synchronizedList() 包装它),则必须同步对列表的所有访问。如果您不这样做,任何事情都可能发生(数据损坏、异常等)。

还有其他的非阻塞列表实现,例如 CopyOnWriteArrayList。但根据用例,它可能比使用同步列表更快或更慢。

【讨论】:

  • 当然,需要注意的是,在使用.synchronized*() 包装器时,用户应确保使用相同的引用 ;)
  • 在您看来,如果我使用hashmap,而不是concurrentHashMap,作为传递字符串的键,并且值为new Object(),我可以阻止它吗?
  • HashMap 和 List 是完全不同的数据结构。当您需要 List 时使用 Map 是没有意义的,反之亦然。 HashMap 也不是线程安全的。同样的答案也适用于 HashMap。这真的闻起来像过早的优化。是什么让您认为同步如此糟糕?
  • 好吧,真实的例子。正如你所说,T1 和 T2 想要同时插入一个字符串,使用 list ,没有同步化是不可能的,我希望每个线程都有相同的可能性到达一个桶而不阻塞,所以我理论化了使用map,因为 map 可以确保或多或少地进行多次插入。
【解决方案2】:

使用Collections.synchronizedList,该列表上的所有单一操作将被同步

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedList(java.util.List)

但请注意,如果您要在该列表上完成多个操作,例如迭代,请使用 synchronized 块来确保列表的完整性,如 javadoc 中所指定:

用户在迭代返回的列表时必须手动同步它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 2011-09-13
    相关资源
    最近更新 更多