HashTable中的ArrayList是线程安全的

时间:2013-01-17 13:49:16

标签: java multithreading arraylist concurrency thread-safety

简单的问题。以下代码是否是线程安全的??

  1. 如果是,有没有更好的方法..?
  2. 如果不是,为什么。?以及如何使其线程安全。
  3. 由于ArrayList Hashtable ArrayList因为Hashtable不是线程安全的,因此我的主要疑问。如果它是Hashtable<Thread, List<String>> threadObjects = new Hashtable<Thread, List<String>>(); // lets assume some object is added. synchronized (threadObjects) { thread = Thread.currentThread(); List<String> v = threadObjects.get(thread); if (null != v) { // do something } } 的一部分,那么同样的事情也会发生。

    {{1}}

    谢谢

3 个答案:

答案 0 :(得分:5)

  

如果是,是否有更好的方法..?

是的,但使用ThreadLocal&gt;

  

我主要怀疑是因为在Hashtable中有ArrayList,因为ArrayList不是线程安全的。

通常你会是对的,但是这段代码确保只有一个线程访问ArrayList。当然,如果你没有遵循这种模式,它将是线程安全的。

注意:synchronized (threadObjects)在这种情况下没有任何区别。

答案 1 :(得分:4)

  

以下代码是否是线程安全的??

是的......只要:

  • 创建地图并向地图添加条目的代码也是线程安全的,
  • 没有其他代码使用地图而不进行同步(根据您的代码)和
  • 没有代码更新列表对象而不在地图上同步。

外部同步数据结构的线程安全性只能通过检查使用数据结构的所有代码来确定。

正如彼得所说,ThreadLocals将是一个更好的解决方案,但如果列表对象在没有适当锁定的情况下发生变异,仍然存在潜在的线程安全问题。

答案 2 :(得分:3)

您可以使用ThreadLocal存储特定于线程的数据。例如:

private final ThreadLocal<List<String>> threadObjects =
    new ThreadLocal<List<String>>() {
        @Override protected List<String> initialValue() {
            return new ArrayList<String>();
        }
    };

public void foo() {
    for (String s : threadObjects.get()) {
        // do something with each string in this thread's list
    }
}

这是一种比Hashtable方法更好的跟踪特定于线程的数据的方法,因为该表是在ThreadLocal实现本身内为您维护的,包括同步。只要您不将引用发布到其他线程,就不需要ArrayList实例上的其他同步;每个线程都有自己的ArrayList实例,因为它没有并发问题。

覆盖initialValue()是一种方便,因为它允许您避免在null的结果上检查threadObjects.get(),当然假设您没有明确设置线程本地null