我有一个对不可变数组的易失性引用,该数组通过用新版本替换引用来异步更改。在此数组上使用 foreach 进行迭代时,是否保证线程安全?
例子:
class MyClass
{
volatile String[] m_array = new String[0];
public synchronized void add(String n)
{ m_array = ArrayUtils.add(m_array, n); // atomic replace
}
public void iterate() // not synchronized!
{ // Do something with each element
for (String s : m_array)
System.out.println(s);
}
}
为什么我问这个问题?
通常,Java 中的 foreach 循环扩展为Iterator:
Iterator<String> i = m_array.iterator();
while(i.hasNext())
...
在这种情况下,只有一次访问m_array 才能有效地获取原子快照。所以一切都很好。
但是,如果未来的 Java 实现为原始数组优化foreach 会怎样,因为在这种情况下迭代器非常慢?(参见foreach 与性能对比)
实现可能会生成类似的代码
for (int i = 0; i < m_array.length; i++)
{ String s = m_array[i];
...
这不再是线程安全的,因为对m_array. 在这种情况下,m_array当字段是 volatile 时,需要一个带有快照的临时变量。
是否保证上述优化永远不会以这种方式发生并且我的代码示例保证安全?
缥缈止盈
相关分类