简单的问题。以下代码是否是线程安全的??
由于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}}
谢谢
答案 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
。