2013-03-17 31 views
0

看來,在執行依賴於Java NIO的服務器,下面的做法是標準:NIO和跨線程的ByteBuffers知名度

使用一個線程(和一個選擇器)用於讀取:

ByteBuffer buffer = . . . 
selector.select() 
... 
channel.read(buffer) 
if (isRequestComplete(buffer)) 
    processRequest(buffer) //will run in a separate thread 

void processRequest(ByteBuffer buffer) 
    new Thread(new Handler(buffer)).start() 

是的,我elliding的代碼大量

我的問題是不是選擇/從通道讀取的機制,而是#buffer的知名度語義被讀入一個單獨的線程比選擇線。我在javadoc中沒有看到任何內容,聲明從線程A(上面的'Handler')中的ByteBuffer讀取可以看到寫入線程B中的ByteBuffer(上面的'選擇器')。
現在,在我看來,上面的代碼根本不是多線程安全的,即它是錯誤的。 但我在許多教程甚至一些代碼庫中都看到過相同的模式(始終沒有引用可視性關注);所以我想知道我是否錯過了一些明顯的東西。

注:我專門側重於在「處理程序」主題永遠只從#buffer讀取情況 - 它從來沒有寫入新的字節到它

回答

1

這其實看起來不錯。你需要的是證明在處理線程中讀入的選擇線程「happens-before」中的寫入。根據內存可見性規則,同一線程中的操作按程序順序發生。新線程的創建也確定了之前的情況。因此,在讀取之前,寫入發生在創建線程之前。

如果將它傳遞到例如一個ExecutorService

+0

是的,非常好的一點。 – igaz 2013-03-17 06:24:38

+1

是的,出色的一點。事實上,另一種解釋我的問題的方法是「在哪裏發生 - 之前」?我已經忘記了有關創建/啓動線程的JMM。顯然,你也可以使用ConcurrentQueues,顯式同步(blecch)和ExecutorService.execute(new Handler(buffer))等等 - 都應該足夠了。 – igaz 2013-03-17 06:31:58