2010-06-29 2 views
1

지난 48 시간 동안 MultithreadingSocket Programming을 이해하려고 노력했습니다. 멀티 쓰레딩을 사용하지 않을 때 소켓 프로그래밍을 구현하고 성공했다. 나는 두 주제에 익숙하지 않으며 같은 주제에 대해 도움이 필요한 스택 자체에 2-3 가지 질문을 제기했다. 멀티 스레딩, 잠금 장치, 소켓 프로그래밍 사용 방법

많이 인터넷 검색 후 나는 Socket ProgrammingMultithreading 설명하는 article을 발견,하지만, 난 여전히이 문서에 의심의 여지가와 기사에서 Figure 5에 붙어있어. 맨 마지막 줄에

private void AcceptConnections() 
    { 
     while (true) 
     { 
      // Accept a connection 
      Socket socket = _serverSocket.Accept(); 
      ConnectionInfo connection = new ConnectionInfo(); 
      connection.Socket = socket; 

      // Create the thread for the receives. 
      connection.Thread = new Thread(ProcessConnection); 
      connection.Thread.IsBackground = true; 
      connection.Thread.Start(connection); 

      // Store the socket 
      lock (_connections) _connections.Add(connection); 
     } 
    } 

당신이 lock 촬영 된과 delegate ProcessConnection 위의 3-4 라인이 결합되어 볼 수 있습니다.

이 시점에서이 잠금이 어떻게 작동하는지 명확하지 않습니다. 자물쇠가 채취 된 뒤에서 무슨 일이 일어나고 있습니까? 저자는 왜 여기에 자물쇠를 사용 했습니까? 자물쇠가 잡히지 않으면 어떻게 됐을까요? 스레드 ProcessConnection은 어떻게 작동합니까? 동시에 어떤 일이 일어나고 있습니까?

나는 모든 질문에 내가 질문 목록 여기가 알고

와 혼동있어,하지만 당신은 멀티 스레딩 작업의 방법론을 이해 도와주세요 수 있다면 큰 도움이 될 것입니다.

답변

2

connection.Thread.Start(connection)ProcessConnection으로 전화하여 connectionstate 인수로 전달하여 새 스레드를 시작합니다. 새 스레드에서 ProcessConnection이 실행되는 동안 현재 스레드의 실행은 다음 줄에서 즉시 계속됩니다.

ProcessConnection은 개체에 개체가 전달되고 AcceptConnections이 전달되고 소켓에서 데이터를 수신하기를 기다립니다. 데이터를 수신하면 connections 콜렉션에있는 다른 ConnectionInfo 오브젝트를 모두 루핑하여이 데이터를 순서대로 각각 전송합니다.

여기서 동시에 실행되는 항목은 무엇입니까? 자, 우리는 무한 루프에서 AcceptConnections을 실행하는 초기 스레드 (스레드 0이라고 함)를 가지고 있습니다.그리고 나서 우리가 수락 한 소켓 연결마다 ProcessConnection을 실행하는 스레드가 있습니다.

ProcessConnectionforeach을 사용하여 알려진 연결을 반복하여 데이터를 보내기 때문에 잠금 장치가 필요합니다. 스레드 0이 foreach에 컬렉션이 열거되는 동안 컬렉션에 새 연결을 추가하는 경우 InvalidOperationExceptionProcessConnection에 던져 질 것입니다.

lock은이 경우 동시성 문제를 방지하지만 잠재적 인 성능 문제도 발생시킵니다. ProcessConnection이 컬렉션을 수정하는 동안 AcceptConnections이 컬렉션을 수정하는 것을 막을뿐만 아니라 또한 ProcessConnection을 실행하는 두 스레드가 동시에 컬렉션을 열거하는 것을 방지합니다. 이 경우 더 나은 선택은 복수 스레드가 동시에 콜렉션을 읽을 수있게하는 ReaderWriterLockSlim입니다.

+0

'로크 (_connections) { 의 foreach (_connections에에서 ConnectionInfo CONN) { 경우 (코네티컷 = 접속!) { conn.Socket.Send ( 버퍼 bytesRead, SocketFlags.None); } } } 이것은 모든 소켓에 동일한 메시지를 브로드 캐스트하는 데 사용 되었습니까? 귀하의 두 번째 단락에서 설명한 바와 같이 –

+0

위대한 설명, 여기서 모든 점을 명확하게. 기사를 참고 자료로 사용하면서 답변을 읽는 중. 내가 그것을 완전히 읽을 때 당신에게 돌아갈 것입니다. –

+0

@Shantanu : 예, foreach 루프는 수신 된 메시지를 다른 모든 소켓으로 브로드 캐스팅하는 루프입니다. –

1

나는 _connectionsList<ConnectionInfo>이라고 가정하고 있습니다. 목록은 threadsafe가 아니며이 스레드는 항목을 해당 목록에 추가합니다. 다른 스레드가 항목을 동시에 제거하면 결과를 예측할 수 없게됩니다. 따라서 잠금을 사용하여 다른 프로세스가 액세스 할 수 없도록해야합니다.

connection.Thread.Start(connection); 즉시 또는 잠시 후 곧 시작될 새로운 글타래를 시작하십시오. 현재 스레드 (여기에 표시되는 코드)는 제어하지 않습니다. 이 새 스레드는 ConnectionInfo 개체와 함께 제공되므로 작업을 수행 할 소켓을 알 수 있습니다. 현재 스레드가 새 클라이언트를 청취하는 동안 ProcessConnection 함수는 최근에 승인 된 클라이언트를 처리합니다.

+0

멋지게 설명해 주시고 귀중한 시간을 보내시기 바랍니다. 여기에 질문이 있습니다. 어떤 객체가 쓰레드 안전하고 어떤 객체가 쓰레드 안전하지 않은지를 아는 법. 항목을 제거하기 위해 _connection에서 잠그면 어떻게 될까요? 그런 다음 같은 목록에 다른 개체를 동시에 추가 할 수 있습니까? –

+0

MSDN에서는 대개 스레드가 안전한지 여부를 알려줍니다. 그들이 말하지 않는다면, 그것이 아니라고 가정해야합니다. 추가 할 때와 목록에서 항목을 제거 할 때 모두 잠금을 사용해야합니다. 그렇지 않으면 예기치 않은 결과가 발생할 수 있습니다. 후드 아래에있는'Add'와'Remove' 메쏘드는 몇 줄의 코드를 실행하고, 동시에 호출하면 서로 물릴 수 있습니다. 그 주위에 자물쇠를 넣으면 한 스레드가 다른 스레드가 자물쇠를 풀 때까지 기다려서 서로를 방해하지 않게됩니다. –

1

C#에서는 일반적으로 CLR에서 모든 개체에 monitor이 연결되어 있다고 생각합니다. 여기 _connections은이 바로 기능에서 시작된 스레드와 공유 될 수있는 콜렉션입니다 (콜렉션이 완료되면 콜렉션에서 연결을 제거 할 가능성이 높음). C#의 컬렉션은 기본적으로 동기화되지 않으므로이를 명시 적으로 수행해야합니다. lock(_connections) 문을 사용하면 컬렉션에 races이 표시되지 않습니다.

+0

제공되는 좋은 링크. THX –