[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 10282] Re: Effective Java 第 5 回議事録



(株)ネットジーンの村山です.

少し考えてみたのですが,

> ■  P160上、この推奨利用方法は、スレッドセーフではない、これでいいのか
>  for (Iterator i = collection.iterator(); i.hasNext();) {
>   Foo foo = (Foo) i.next();
>   ............
>  }
>  むしろ
>  try {
>    Iterator i = collection.iterator();
>    while(true) {
>      Foo foo = (Foo )i.next();
>      ....
>    }
>  } catch (NoSuchElementException e) {
>  }
>  はたとえどんなに遅くとも、平行操作に対する耐性が有る。
>  他のスレッドからiteratorをいじられても感知できる。

たぶん,下のやりかたでもスレッドセーフになってないと思います.
他のスレッドがそのコレクションクラスを書き換えている最中に,
同時に読み出したりするとデータの整合性が失われたりする可能性が
あるのでは.
#具体的にどのような不具合が生じるかは実装依存のはず.

これを避けるにはコレクションクラス関連のメソッドを全て同期化
する他ないですが,そうするとVectorやHashtableと同様にパフォー
マンスが劇的に低下する恐れがあります.よほど無茶な設計をしない
限り,そういうことはしないでしょう.
#VecotorやHashtableが,まさにこれだったりしますが....(^^;

> try{
>  ...
> }catch(ConcurrentModificationException e){
>  ...
> }

また,java.util.ConcurrentModificationExceptionの
ドキュメントでも次の様に書かれています.
#日本語としては,少し解り難かったりしますが..

-----------------------------
通常、非同期の同時変更がある場合、確かな保証を行うことは不可能
なので、フェイルファストの動作を保証することはできません。
フェイルファストオペレーションは最善努力原則に基づき、
ConcurrentModificationException をスローします。したがって、
正確を期すためにこの例外に依存するプログラムを書くことは誤り
です。ConcurrentModificationException は、バグを検出するため
にのみ使用すべきです。 
-----------------------------

ましてや,NoSuchElementExceptionやコレクションフレームワーク
では同期化していることはまずないと思います.

最初の例でスレッドセーフにしたければ,プログラマーが自前で
同期処理を行うべきです.その際には,可能ならばループ内で
Synchronizedメソッド/文を使うよりは,ループ外のレベル/
アルゴリズムのレベルで危険なアクセスが同時に起こらないことを
保証した方が無難でしょう.

#ところで,一般的に言って,マルチスレッドセーフなクラスって,
#ほとんど使い道はないものです.一般的にMT-Safeにするには,
#過剰なまでに同期化する他はなく,ある特定のアプリで使用する
#にはオーバーヘッドが大きすぎます.それに,マルチスレッドで
#使うプログラムを設計する際は,いずれにせよ同期処理を完全に
#把握する必要があるのでプログラマーの負担が軽減されるわけ
#でもありません.

#ぶっちゃけた話,同期をMT-Safeなクラスや過剰な同期に頼るのは
#二流プログラマーの証.