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
Is java.util.Calendar thread safe or not?
提问by Daniel C. Sobral
I've been working under the assumption that neither Date
nor Calendar
are thread-safe, but, during a recent discussion, a co-worker told me Calendar
was 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中Calendar和GregorianCalendar源代码的链接
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 get
methods 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 Calendar
class is not thread-safe, and GregorianCalendar
isn'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.Calendar
in 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.
我认为可以安全地假设该类不是线程安全的。