如果此方法的变量“commonSet”改为类级字段,以下代码是否会导致同样的问题。如果它是一个类级别的字段,我将不得不在一个同步块(synchronized block)中将添加到集合操作包装起来,因为 HashSet 不是线程安全的。我是否应该在下面的代码中做同样的事情,因为多个线程正在添加到集合中,甚至当前线程可能会继续改变集合。
public void threadCreatorFunction(final String[] args) {
final Set<String> commonSet = new HashSet<String>();
final Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
commonSet.add(newValue());
}
}
};
new Thread(runnable, "T_A").start();
new Thread(runnable, "T_B").start();
}
对“commonSet”的引用通过使用 final 被“锁定”。但是对其进行操作的多个线程仍然可以破坏集合中的值(它可能包含重复项?)。其次,混淆是因为“commonSet”是一个方法级变量——它的相同引用将在调用方法 (threadCreatorFunction) 的堆栈内存和运行方法的堆栈内存上——这是正确的吗?
有很多与此相关的问题:
- Why do variables passed to runnable need to be final?
- Why are only final variables accessible in anonymous class?
但是,我看不到他们强调这种共享/传递可变变量的线程安全部分。
最佳答案
不,这绝对不是线程安全的。仅仅因为您将它放在最终变量中,这意味着两个线程将看到相同的引用,这很好 - 但它不会使对象成为任何对象更线程安全。
要么需要同步访问,要么使用ConcurrentSkipListSet
.
关于java - 线程安全 - 传递给线程的最终局部方法变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11824264/