26

私はスレッドセーフでもないという仮定の下で作業してきましたDateCalendar、最近の議論の中で、同僚が私Calendarにスレッドセーフであると言いました。

それで、私はいくつかの調査をしました、そして何も思いつきませんでした。スレッドセーフであると主張する人はたくさんいますし、スレッドセーフではないと主張する人もたくさんいます。Calendarそして、それを締めくくりに、ドキュメントは、のために、あるいはのためにさえ、何らかの形で何も述べていませんDate

それで、それはどれですか?

4

2 に答える 2

37

Java7のCalendarGregorianCalendarのソースコードへのリンクは次のとおりです。

コードを読むと、どのインスタンスメソッドも同期されておらず、どのインスタンスフィールドも同期されていないことがわかりますvolatilegetまた、fieldメソッドでさえ、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でクラスのスレッドセーフが指定されていない場合は、スレッドセーフではないと見なす必要があります。(特に、クラスが設計により変更可能である場合。)

于 2012-08-26T16:20:16.053 に答える
4

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

クラスはスレッドセーフではないと想定しても安全だと思います。

于 2012-08-26T16:15:28.533 に答える