Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

protecting selector key set  RSS feed

 
Andrew Gaydenko
Greenhorn
Posts: 10
Firefox Browser Linux Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this article

http://today.java.net/pub/a/today/2007/02/13/architecture-of-highly-scalable-nio-server.html

Gregor Roth refers to Ron Hitchens' slides

http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1315.pdf

wrt "guard object idiom". A fragment I can not understand is below.

At first look, after empty synchronized block finished, nothing prevents some thread to start key set changing while selector.select() is running.

Have I missed something?


 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, it doesn't prevent key-set changing from occurring while the selector.select() is running. The selector's key-set and selected-key-set are not thread safe. Any of the threads which can modify the key-set should be synchronized, like they are in the example code. However the selection thread with the empty synchronized block is using the selected-key-set. The working threads those articles talk about aren't modifying the selected-key-set directly, they modify the state of the SelectorKeys and thus the key-set. The select() method actually makes the selected-key-set, which is not thread safe, but since the selected-key-set is only being accessed in the same thread that created it it does not need to be synchronized. So it is important that you only access the selected-key-set from the thread in which the select() was called.

What the guard idiom is doing is preventing race conditions and un-ending blocking from occurring when register() methods are called while the select() method has already been called. By placing a wakeup() call before the register() call, and both of these inside a synchronized block, and putting an empty synchronized block in front of your select() method you are ensuring that the register() doesn't occur while the select() is holding on to the key-set lock and sleeping - waiting for the wakeup() method to be called. Take away the empty synchronized block and you could get a situation like this:

1) selection thread select()s, lock on key-set and goes to sleep
a) other thread wakeup()s
2) selection thread select() makes selected-key-set, releases key-set lock
3) selection thread iterates over selected-key-set
1) selection thread select()s, lock on key-set and goes to sleep
b) other thread register()s, attempts lock on key-set, blocks

This sequence with the empty synchronized block would be modified as such:
1) selection thread locks on guard
2) selection thread released lock on guard
3) selection thread select()s, lock on key-set and goes to sleep
a) other thread locks on guard
b) other thread wakeup()s
4) selection thread iterates over selected-key-set
1) selection thread tries to lock on guard, blocks
c) other thread register()s, locks on key-set, releases key-set lock
d) other thread releases guard lock
1) selection-thread locks on guard
etc...

An examination of this last scenario might show a weakness, like, what if 1) and 2) occur, then a) and b), then 3) then c)? The synchronization doesn't help here, we still have the select() called before the register(). The answer to this is the wakeup() will not only wakeup the currently sleeping select() methods, but if there aren't any sleeping select() threads then it will prevent the next select() method from sleeping. So there is no problem as long as we call the wakeup() before the register(). The only problem is if there are 2 select()s that occur between the wakeup() and the register(), which the synchronized blocks make impossible.
 
Andrew Gaydenko
Greenhorn
Posts: 10
Firefox Browser Linux Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Steve, thanks! I have missed the key moment - wakeup() call at the beginninng of other synced blocks.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!