2013-03-17 2 views
0

는 자바 NIO에 의존하는 서버를 구현, 다음과 같은 연습 표준 것 같다 :NIO 스레드에서 ByteBuffer의 가시성

를 사용하여 단일 스레드 (단일 선택)에 대한 읽기 :

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() 

예, 상당한 양의 코드를 제외 시켰습니다.

제 질문은 채널을 선택하거나 읽는 방법에 관한 것이 아니라 오히려 선택자와 다른 스레드에서 읽을 수있는 #buffer의 가시성 의미에 관한 것입니다. 실. javadoc에서 Thread A ('Handler')의 ByteBuffer에서 읽는 것이 Thread B (위에서 'Selector')의 ByteBuffer에 대한 쓰기를 볼 수 있음을 알 수 있습니다.
위의 코드는 단순히 다중 스레드로부터 안전하지는 않습니다. 즉, 잘못되었습니다. 그러나 나는 많은 자습서와 심지어 일부 코드베이스 (항상 가시성 문제를 참조하지 않고도)에서 같은 패턴을 보았습니다. 그래서 나는 명백한 것을 놓치고 있는지 궁금해.

참고 : 나는 특히 '핸들러'스레드는 오직 #buffer에서를 읽고 상황에 국한하고있어 - 그것이

답변

1

이 실제로 확인을 보인다에 새로운 바이트를 기록하지 않았다. 필요한 것은 핸들러 쓰레드에서 쓰레드 "happens-before"을 쓰는 것을 증명하는 것입니다. 메모리 가시성 규칙에 따르면 동일한 스레드의 동작은 프로그램 순서로 발생합니다. 새로운 쓰레드를 생성하면 일이 벌어집니다. 따라서 쓰기 전에는 스레드 생성 전에 스레드가 생성되기 전에 읽습니다.

예 : ExecutorService.

+0

예, 우수합니다. – igaz

+1

예, 훌륭한 지적입니다. 실제로, 나의 질문을 표현하는 또 다른 방법은 "어디에서 일어난 일이 일어나는가"입니다. 스레드의 생성/시작에 관한 JMM을 잊어 버렸습니다. 분명히 ConcurrentQueues, 명시 적 동기화 (blecch) 및 ExecutorService.execute (new Handler (buffer)) 등을 사용할 수도 있습니다. – igaz