Sunday, 5 October 2008

Java の synchronized

結局、学生の書いたコードが気に入らなくてガンガン書きなおしていて、実際のプロトコルの方が後回しになっていたりしますが...

 Collections.synchronizedMap(new HashMap<SelectableChannel,SelectableChannel>()); 
とかいう方法で、Map(Set)自体をThread safeにすると言う手があるらしい。なんだが、

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views

Interator はだめなのか。やってくれたって良いと思うんだが。どうせ、明示的なsynchronized 文がいるなら、それを持っているObjectのmethodに synchronized を付ける方が良いと思う。

このあたりは趣味かも知れないけど、Thread safe でないオブジェクトに外部からlockするよりは、自分からlockする方が、lockを複数取る危険性がないのと、オブジェクトの状態が明示的になるので良い気がする。確かに、synchronized(hoge) {} の方が、concurrency は上がるんだけど。

 class synchronized Hoge extend HashMap { }

みたいな形で書きたい気がする。その方が並列オブジェクトっぽい。Java は、finalとか付いているmethodが結構あって、この手の書き方がダメで、どうしても明示的にHashMapを持ってdelegateする形になるんだよな。使いづらいです。

もっとも、あまりlockを広げすぎると dead lockしやすくなるんだけど。ABCL/1で now 型ばかり使うような感じか。futureがあると楽なんですが、java.util.concurrentのは、ちょっと構文的にも実装的にも重すぎる。

  ────────────────────────────────

selector.select() の戻り値が、どうも信用できない。selector.keys() で取って来ると取れるんだけど、0を返している時があるみたいです。そもそも、

 Thread A          Thread B
 selector.select();     selector.select();
 selector.keys();     selector.keys();

と二つに分けて取っているあたりが、thread safeじゃないし。まぁ、一つのselectorを二つのthread使うなってことだよな。Documentには、Selectorはsafeで、SelectedKeyは違うみたいなことが書いてあるが...

Selectors are themselves safe for use by multiple concurrent threads; their key sets, however, are not.

select() した後、keys(),it.remove() されると、それをresetするみたいな動作になっているっぽい。for(SelectedKeys key:selector.keys()) が動かない理由も、それかな。

No comments: