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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12131324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:42:43  来源:igfitidea点击:

Is java.util.Calendar thread safe or not?

javacalendar

提问by Daniel C. Sobral

I've been working under the assumption that neither Datenor Calendarare thread-safe, but, during a recent discussion, a co-worker told me Calendarwas thread-safe.

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

So, I did some research, and came up with nothing. There are plenty people arguing it's thread-safe, and plenty people arguing it's not thread-safe. And, to top it off, the documentation doesn't say anything one way or another, not for Calendar, nor even for Date.

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

So, which is it?

那么,它是哪个?

回答by Stephen C

Here is a link to the source code of Calendarand GregorianCalendarin Java 7

这是Java 7中CalendarGregorianCalendar源代码的链接

If you read the code you will see that none of the instance methods are synchronized, and none of the instance fields are volatile. You will also see that even the field getmethods can cause a Calendar instance to mutate. And since there is no synchronization performed, different threads may see stale versions of a Calendar object's fields following such a mutating operation.

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

For the record, the mutation action in the field get methods happens in / during a call to this method:

作为记录,在调用此方法期间,字段 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       }

In short, the Calendarclass is not thread-safe, and GregorianCalendarisn't either because it inherits the non-thread-safe fields and methods.

简而言之,Calendar该类不是线程安全的,GregorianCalendar也不是因为它继承了非线程安全的字段和方法。

But don't just take my word for it. Do your own analysis of the source code.

但不要只相信我的话。对源代码进行自己的分析。



And, to top it off, the documentation doesn't say anything one way or another, not for Calendar, nor even for Date.

而且,最重要的是,文档没有以任何方式说明任何内容,不适用于日历,甚至也没有说明日期。

If the javadocs don't specify the thread-safety of a class, then you should assumethat it is not thread-safe.

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

回答by yegor256

Documentation from Oracle says nothing about thread-safety: http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html.

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

OpenJDK source code (build b147) implements java.util.Calendarin a non-thread-safe way, for example:

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

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

I think that it's safe to assume that the class is notthread safe.

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