java.util.Calendar线程是否安全?

时间:2012-08-26 15:24:38

标签: java calendar

我一直在假设DateCalendar都不是线程安全的,但在最近的讨论中,一位同事告诉我Calendar是线程安全的。

所以,我做了一些研究,并没有提出任何建议。有很多人认为它是线程安全的,很多人认为它不是线程安全的。而且,最重要的是,文档不会以某种方式说出任何内容,不是Calendar,甚至也不是Date

那么,这是什么?

3 个答案:

答案 0 :(得分:28)

以下是Java 7中CalendarGregorianCalendar源代码的链接

如果您阅读代码,您将看到没有任何实例方法同步,并且所有实例字段都不是volatile。您还将看到即使是字段get方法也可能导致Calendar实例发生变异。并且由于没有执行同步,因此不同的线程可能会在这样的变异操作之后看到Calendar对象的字段的陈旧版本。

对于记录,字段get中的变异操作在调用此方法时/期间发生:

 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没有指定类的线程安全性,那么你应该假设它不是线程安全的。

答案 1 :(得分:4)

Oracle的文档没有提及线程安全性:http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

OpenJDK源代码(build b147)以非线程安全的方式实现java.util.Calendar,例如:

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

我认为可以安全地假设该类线程安全。

答案 2 :(得分:-1)

- 我不确定您的朋友从哪里获取信息,但是用简单直接的语言说话,Calendar class is Thread safe

- 我没有在原子语句中找到任何synchronized个关键字,也没有在Calendar类及其子类中找到volatile个字段。