2012-07-17 105 views
0

在我的應用程序中,我使用多個線程來處理客戶端連接。我有一個SelectionKey,通過調用(使用調試器)它的interestOps()方法的返回值是1(READ),但是當我發送數據到相應的套接字鍵選擇器不會醒來。Java:SelectionKey.interestOps(int)不是線程安全的?

如果使用調試器,我將特定的選擇鍵興趣ops更改爲1(即使它是1),選擇器突然對這種更改作出反應。

我只有一個線程在給定時間處理連接,但是此線程不是特定於該連接的,如果禁用多線程(將線程池設置爲1號大小),則永遠不會發生此問題。

通過查看SelectionKey類文檔 - 此方法應該是線程安全的 - 我錯過了什麼嗎?

+0

兩者你真的步入源代碼? javadoc並不總是提到一個方法是否是線程安全的。 – user1329572 2012-07-17 13:31:06

+0

@ user1329572是的,該方法做了2件重要的事情 - 更改自己感興趣的操作字段,然後調用通道的translateAndSetInterestOps方法 - 這是我認爲問題發生的地方,但正如我所說 - 我只有一個線程處理連接時間,我也在同步密鑰時更改其interestOp,但沒有修復bug .. – bennyl 2012-07-17 13:37:47

回答

2

這個問題是在我將感興趣的所有更改移到選擇器線程上後解決的 - 所以我猜這個interestOps(int)不是線程安全的。

編輯
由所有interestOps改變移動到選擇線程我也收穫了30%的加速 - 不知道爲什麼,但是這是我的測試之間的唯一的變化..

2

這不是線程的問題安全。如果當前正在執行select(),則它已經從所有註冊密鑰中讀取了所有interestOps,並正在選擇讀取時的值:這些值將傳遞到操作系統,並且操作系統阻止操作處於進展。在選擇操作過程中更改interestOps不會影響該選擇操作,只會影響下一個操作。

+0

我在喚醒每個鍵更改後的選擇器 - 這沒有幫助..我甚至使用select(int)方法超時只是10秒,看看這種行爲是否可以使用選擇器「固定」 - 事實並非如此。 – bennyl 2012-07-18 07:46:12

0

我有點遲到了,但人誰都會像我一樣,在參觀未來:

「選擇鍵是由多個併發線程安全的讀操作和通常,寫興趣集將與選擇器的某些操作同步。「

"SelectionKey in Java 7"

+1

重要的是要明白,他們可以阻止選擇器正在選擇 - 這可能會導致死鎖。所以雖然他們在術語的「正確性」方面在技術上是安全的,但他們在術語 – bennyl 2016-11-06 10:56:40

+0

的「進度」方面不太安全。是的,我學會了這一難題。一般來說,即使認爲這個解決方案是以創建速度和效率的方式創建的,但它並沒有達到預期。在連接到其他主機的情況下(所以當創建通道,註冊選擇器並設置興趣操作)時,需要創建額外的鎖,並執行如下操作:selKey.interestOps(OP_WRITE); lock.lock(); selector.wakeUp();同時連接,然後執行以下操作:選擇器。選擇(); synchronized(lock){};在選擇器循環中 - 否則選擇器可以喚醒並進入休眠狀態。 – 2017-01-02 13:38:10

+1

實際上,您可以使用比鎖更好的解決方案:只需創建一個'ConcurrentLinkedQueue selectorOps'字段,並在每次選擇並運行該隊列中的所有可運行內容後立即在該隊列上運行選擇器線程。然後,如果你想改變一些關鍵的操作,你所要做的就是調用:'selectorOps.add(() - > key.interestedOps(ops)); selector.wakeup();' - 不需要鎖定。 – bennyl 2017-01-02 16:48:15