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:
Post a Comment