2010-06-29 82 views
1

過去48小時,我一直試圖瞭解MultithreadingSocket Programming。我試圖實現套接字編程,並在不使用多線程時取得了成功。我對這兩個主題都很陌生,並且在堆棧本身提出了2-3個問題,需要相同的幫助。如何使用多線程,鎖,套接字編程

google搜索了很多後,我發現了一個article解釋Socket ProgrammingMultithreading,但還是有很多疑惑的這篇文章中,並在文章中被困在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已經採取和3-4線delegate ProcessConnection上面的約束。

在這一點上,我不清楚這個鎖是如何工作的。鎖已經發生在幕後的事情是什麼?爲什麼作者在這裏使用鎖定?如果沒有鎖定,會發生什麼?線程ProcessConnection如何工作?什麼事情同時發生?

我弄糊塗了所有這些問題

我知道有一個問題清單在這裏,但是這將是一個很大的幫助,如果你能幫助我瞭解多線程工作的方法。

回答

2

connection.Thread.Start(connection)啓動一個新線程來ProcessConnection通話,傳遞connectionstate參數。當前線程中的執行會立即繼續執行下一行,而在新線程中執行ProcessConnection

ProcessConnection從傳遞給它的ConnectionInfo對象中獲取Socket對象AcceptConnections並等待從套接字接收數據。當它接收到數據時,它循環訪問connections集合中的所有其他ConnectionInfo對象,並將這些數據按順序發送給它們中的每一個。

那麼這裏同時運行什麼?那麼,我們有最初的線程(稱爲線程0)在無限循環中執行AcceptConnections。然後對於我們接受的每個套接字連接,我們有一個執行ProcessConnection的線程。

鎖是需要的,因爲ProcessConnection使用foreach循環通過已知的連接發送它們的數據。如果線程0在集合正在枚舉foreach時向該集合添加新連接,則將在ProcessConnection中拋出InvalidOperationException

lock在這種情況下確實避免了併發問題,但它也會導致潛在的性能問題。它不僅防止AcceptConnections修改集合,而ProcessConnection正在枚舉它。它還可以防止執行ProcessConnection的任何兩個線程同時枚舉集合。在這種情況下更好的選擇是ReaderWriterLockSlim,這將允許多個線程同時讀取集合。

+0

'鎖(_connections) { 的foreach(ConnectionInfo康恩在_connections) { 如果(參數conn =連接!) { conn.Socket.Send( 緩衝器,bytesRead,SocketFlags.None); } } }'這已用於向每個套接字廣播相同的消息?正如您在第二段 – 2010-06-29 13:57:05

+0

中解釋的那樣,很好的解釋,在這裏明確所有要點。仍然閱讀您的答案,並將文章作爲參考。當我完全閱讀時會回覆給你。 – 2010-06-29 13:59:19

+0

@Shantanu:是的,那個foreach循環是將收到的消息廣播到其他每個套接字的環。 – 2010-06-29 14:08:23

1

我假設_connectionsList<ConnectionInfo>:列表不是線程安全的,並且此線程將項目添加到該列表。如果另一個線程將同時移除一個項目,結果將是不可預測的。所以你必須確保沒有其他進程可以使用鎖來訪問它。

connection.Thread.Start(connection);啓動一個新的線程,該線程將立即啓動或即將啓動。當前線程(您在這裏看到的代碼)將無法控制它。這個新線程提供了一個ConnectionInfo對象,所以它會知道在哪個套接字上執行任務。在當前線程不斷收聽新客戶端時,ProcessConnection函數將處理最近接受的客戶端。

+0

很好地解釋和thx爲您寶貴的時間以及。我在這裏有一個問題。如何知道哪個對象是線程安全的,哪個不是。如果我在_connection上取消鎖定項目,會發生什麼情況。然後我可以在同一時間添加另一個對象到同一個列表中。 – 2010-06-29 13:33:06

+0

在MSDN上,他們通常會告訴你一個對象是否是線程安全的。如果他們不說,你應該認爲它不是。 您應該在添加時以及從列表中刪除項目時使用鎖定,否則您可能會收到意外的結果。引擎蓋下的Add和Remove方法執行幾行代碼,當你同時調用它們時,它們可能會咬人。鎖定它會使一個線程等待另一個線程釋放它的鎖,所以它們不會互相干擾。 – 2010-06-29 14:00:50

1

在C#中,我認爲在CLR中,每個對象可能都有一個與之關聯的monitor。這裏_connections是一個集合,它可能與從這個非常功能啓動的線程共享(它們可能在完成時從集合中刪除連接)。 C#中的集合默認是不同步的,你必須明確地這樣做,因此lock(_connections)聲明可以防止集合上的races

+0

提供了不錯的鏈接。 THX – 2010-06-29 13:35:03