Подтвердить что ты не робот

Является ли java.util.Calendar потоком безопасным или нет?

Я работал в предположении, что ни Date, ни Calendar не являются потокобезопасными, но во время недавнего обсуждения один из сотрудников сказал мне, что Calendar был потокобезопасным.

Итак, я сделал некоторые исследования и ничего не придумал. Есть много людей, которые утверждают, что они потокобезопасны, и много людей утверждают, что это не потокобезопасно. И, в довершение всего, документация ничего не говорит так или иначе, а не для Calendar и даже для Date.

Итак, что это?

4b9b3361

Ответ 1

Вот ссылка на исходный код Calendar и GregorianCalendar в Java 7

Если вы прочитаете код, вы увидите, что ни один из методов экземпляра не синхронизирован, и ни одно из полей экземпляра не является volatile. Вы также увидите, что даже методы поля get могут вызвать изменение экземпляра календаря. И поскольку синхронизация не выполняется, разные потоки могут видеть устаревшие версии полей объекта Calendar, следующих за такой мутирующей операцией.

Для записи, действие мутации в методе получения поля происходит в/во время вызова этого метода:

 1555 protected void complete()
 1556       {
 1557           if (!isTimeSet)
 1558               updateTime();
 1559           if (!areFieldsSet || !areAllFieldsSet) {
 1560               computeFields(); // fills in unset fields
 1561               areAllFieldsSet = areFieldsSet = true;
 1562           }
 1563       }

Короче говоря, класс Calendar не является потокобезопасным, а GregorianCalendar - не потому, что он наследует непоточные поля и методы.

Но не задумывайтесь об этом. Сделайте свой собственный анализ исходного кода.


И, в довершение всего, документация ничего не говорит так или иначе, а не для Календаря и даже для даты.

Если javadocs не определяют безопасность потока для класса, вы должны предположить, что он не является потокобезопасным.

Ответ 2

Документация от Oracle ничего не говорит о безопасности потоков: http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html.

Исходный код OpenJDK (сборка b147) реализует java.util.Calendar небезобезопасным способом, например:

public void setTimeInMillis(long millis) {
  // skipped
  time = millis;
  isTimeSet = true;
  areFieldsSet = false;
  computeFields();
  areAllFieldsSet = areFieldsSet = true;
}

Я думаю, что можно с уверенностью предположить, что класс не потокобезопасен.

Ответ 3

- Я не уверен, откуда ваш друг получил информацию, но говоря простым и понятным образом, Calendar class is не Thread safe.

- Я не нашел ни одного слова synchronized для атомных операторов, ни полей volatile в классе Calendar, ни в его подклассах.