Consider the request-response protocol.
We create a thread to execute a select() loop to read and write to a received non-blocking SocketChannel . It might look something like this:
while (!isStopped()) { selector.select(); Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator(); while (selectedKeys.hasNext()) { SelectionKey selectedKey = selectedKeys.next(); selectedKeys.remove(); Context context = (Context) selectedKey.attachment(); if (selectedKey.isReadable()) { context.readRequest(); } else { context.writeResponse(); } } }
where Context is just a container for the corresponding SocketChannel , a buffer and logic to read into and write from it. readRequest might look like
public void readRequest() { // read all content socketChannel.read(requestBuffer); // not interested anymore selectionKey.interestOps(0); executorService.submit(() -> { // handle request with request buffer and prepare response responseBuffer.put(/* some response content */); // or set fields of some bean that will be serialized // notify selector, ready to write selectionKey.interestOps(SelectionKey.OP_WRITE); selectionKey.selector().wakeup(); // worried about this }); }
In other words, we read from the socket channel, fill up some buffer and pass processing to another thread. This thread performs the processing and prepares the response that it stores in the response buffer. He then notifies the selector that he wants to write and wakes up.
The javadoc for Selector#wakeup() does not mention any events - before the relationship, so I worry that the selector stream can see the response buffer (or some intermediate object) in an inconsistent state.
Is this a possible scenario? If so, what is the correct way to pass the response that should be written to the SocketChannel stream by the Selector loop stream? (Posting the response through some volatile field? Using the SelectionKey attachment? Another form of synchronization?)
source share