LoginSignup
0
0

More than 5 years have passed since last update.

Item 82: Document thread safety

Posted at

82.スレッドセーフティについてドキュメントすべし

  • 提供するメソッドを並列実行させた時の挙動は、クライアントとの重要な約束事であり、ドキュメントとして明記しないとエラーを招くこととなる。
  • sychronized句の有無でスレッドセーフであるかを見分けることはできない。
  • スレッドセーフという性質はオールオアナッシングなものではなく、数段階のレベルがあるものである。以下、スレッドセーフの各レベルを要約する。

    • Immutable:状態は常に一貫しており、外部での同期は必要ない。 ex)String,Long,BigInteger
    • Unconditionally thread-safe:mutableなインスタンスであるが、内部で十分に同期がとれているので、外部での同期は必要ない。 ex)AtomicLong,ConcurrentHashMap
    • Conditionally thread-safe:Unconditionally thread-safeに似ているが、一部のメソッドでは外部での同期が必要となる。 ex)Collections.synchronized のラッパークラス。これらのiterators は外部の同期が必要となる。
    • Not thread-safe:並列処理をしようと思ったら必ず外部で同期が必要となる。 ex)ArrayList,HashMap
    • Thread-hostile:外部で同期をかけてもスレッドセーフにならない。たいていはstaticなデータを同期なしで変更していることによる。 ex)Item78のgeneralSerialNumber メソッド
  • クラスのスレッドセーフティについてはクラスのJavadocに書くべきで、スレッドセーフティに関して特別な考慮が必要なメソッドには、そのJavadocに記述する。以下のCollections.synchronizedMapが好例。

    /**
     * It is imperative that the user manually synchronize on the returned
     * map when traversing any of its collection views via {@link Iterator},
     * {@link Spliterator} or {@link Stream}:
     * <pre>
     *  Map m = Collections.synchronizedMap(new HashMap());
     *      ...
     *  Set s = m.keySet();  // Needn't be in synchronized block
     *      ...
     *  synchronized (m) {  // Synchronizing on m, not s!
     *      Iterator i = s.iterator(); // Must be in synchronized block
     *      while (i.hasNext())
     *          foo(i.next());
     *  }
     * </pre>
     */
    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }
  • Unconditionally thread-safe なクラスを書くにあたっては、synchronized なメソッドの代わりにprivate lockを使う手法がある。これによって、クライアント、サブクラスからの悪意ある同期から守ることができる。(DOSの例を挙げていたが、どうやって起こすのかいまいちわからない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0