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

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

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

那么,这是什么?

这是Java 7中Calendar和GregorianCalendar源代码的链接

如果您阅读代码,您将看到没有任何实例方法同步,并且所有实例字段都不是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也不是因为它inheritance了非线程安全的字段和方法。

但是,不要只听我的话。 自己分析源代码。


而且,最重要的是,文档不会以任何方式说出任何内容,不是针对日历,甚至也不是针对日期。

如果javadocs没有指定类的线程安全性,那么您应该假设它不是线程安全的。

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; } 

我认为假设该类不是线程安全的是安全的。

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

我没有在primefaces语句中找到任何synchronized关键字,也没有在Calendar类和子类中找到volatile字段。