У меня есть изменчивая ссылка на неизменный массив, который асинхронно изменяется путем замены ссылки новой версией.Гарантируется ли потокобезопасность при итерации с 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);
}
}
Почему я задаю этот вопрос?
Обычно цикл foreach в Java расширяется до 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
требуется, когда поле является изменчивым.
Гарантируется, что вышеописанная оптимизация никогда не произойдет таким образом, и мой пример кода гарантированно безопасен?