私自身のアプリケーションを徹底的にテストした後、私はこれにいくらかの光を当てることができるかもしれません。私が観察した現象は次のとおりです。
開いてAで処理されたJava を、並行するBから閉じると、呼び出しがAの次の呼び出しまでブロックされることがあり、その後、再実行されて。を示します。BのinとAのanyの非同期呼び出しの間で、Aはそのソケットで正常に操作を実行できます。SSLSocket
Thread
Thread
close()
read()
Thread
EOF
close()
Thread
read()
Thread
write()
これは、 Aによって開始された呼び出しが終了する前にThread
Bが実行する場合にのみ当てはまることがわかりました。その後、非同期で閉じても問題ないようです。close()
startHandshake()
Thread
SSLSocket
これは、問題をどのように解決するかという問題を私たちに残します。明らかに、状態ベースの動作が少し役立つでしょう。
Bで非同期の遅延が発生する可能性がある場合、close()
AがSSLセッションの準備ができるまでBを待機させるため、 beforeの呼び出しは非常にうまく機能しているようです。ただし、これによりソケットごとに遅延が発生する可能性があります。また、 Aがソケットの使用を開始する前にBでが実行されない場合は、追加の作業が発生する可能性があります。Thread
getSession()
close()
close()
Thread
より良い、しかしそれほど単純ではない解決策は、2つの単方向フラグを使用することです。1つ(handshakeDone
)は、SSLハンドシェイクが完了したことを示すためにAによって使用されます( Bがこれを見つけるための非ブロッキングAPIの方法はありません)。もう1つの(toBeClosed
)は、ソケットが閉じていることを示すためにBによって使用されます。
toBeClosed
ハンドシェイクが実行された後にチェックします。Bは、falseの場合に呼び出すclose()
か、そうでない場合に設定します。handshakeDone
toBeClosed
これを成功させるには、AとBの両方にアトミックブロックが必要であることに注意してください。特定の実装(上記のアルゴリズムと比較して最適化されている可能性があります)はあなたに任せます。
close()
ただし、SSLソケットでの非同期呼び出しが誤動作する状況が他にもある可能性があります。