0

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

  1. 如果是的话,有没有更好的方法..?
  2. 如果没有,为什么。?以及如何使其线程安全。

我的主要怀疑是因为内部ArrayList不是线程安全的。所以同样的事情会发生,如果它的一部分。HashtableArrayListHashtable

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
     }
  }

谢谢

4

3 回答 3

5

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

是的,但使用 ThreadLocal>

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

通常你是对的,但是这段代码确保了一个 ArrayList 只能被一个线程访问。当然,如果您不遵循此模式,那将是线程安全的。

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

于 2013-01-17T13:52:16.953 回答
4

以下代码是线程安全的吗...?

是的……前提是:

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

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

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

于 2013-01-17T14:41:44.537 回答
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

于 2013-01-17T14:55:17.767 回答