过去48小时内,我一直在尝试了解Multithreading
和Socket Programming
。我尝试实现套接字编程,并在不使用多线程时取得了成功。我是这两个主题的新手,并且已经在堆栈上提出了2-3个问题,需要帮助。
经过Google搜索后,我找到了解释Socket Programming
和Multithreading
的 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线程如何工作?什么事情同时发生?
我对所有这些问题感到困惑
我知道这里有一个问题列表,但是如果你能帮助我理解使用多线程的方法,那将是一个很大的帮助。
答案 0 :(得分:2)
connection.Thread.Start(connection)
启动一个新线程,调用ProcessConnection
,将connection
作为state
参数传递。在新线程中执行ProcessConnection
时,当前线程中的执行会立即继续执行下一行。
ProcessConnection
从Socket
传递给它的ConnectionInfo
对象获取AcceptConnections
对象,并等待从套接字接收数据。当它接收数据时,它会遍历ConnectionInfo
集合中的所有其他connections
个对象,并按顺序将这些数据发送给每个对象。
那么这里同时运行的是什么?好吧,我们有一个初始线程(称之为线程0)在无限循环中执行AcceptConnections
。然后对于我们接受的每个套接字连接,我们有一个执行ProcessConnection
的线程。
需要锁定,因为ProcessConnection
使用foreach
循环已知连接以向其发送数据。如果在foreach
中枚举集合时,线程0要向集合添加新连接,则InvalidOperationException
中将抛出ProcessConnection
。
lock
确实可以防止这种情况下的并发问题,但它也会导致潜在的性能问题。它不仅阻止AcceptConnections
在ProcessConnection
枚举时修改集合。它还可以防止执行ProcessConnection
的任何两个线程同时枚举集合。在这种情况下,更好的选择是ReaderWriterLockSlim
,它允许多个线程同时读取集合。
答案 1 :(得分:1)
我假设_connections
是List<ConnectionInfo>
:列表不是线程安全的,并且此线程将项添加到该列表中。如果另一个线程同时删除一个项目,结果将是不可预测的。所以你必须确保没有其他进程可以使用锁来访问它。
connection.Thread.Start(connection);
启动一个新的线程,它将立即启动或很快启动。当前线程(您在此处看到的代码)将无法对其进行任何控制。这个新线程虽然提供了ConnectionInfo
对象,但它将知道在哪个套接字上执行任务。当前线程一直在监听新客户端,ProcessConnection
函数将处理最近接受的客户端。
答案 2 :(得分:1)