如何使用多线程,锁,套接字编程

时间:2010-06-29 13:17:03

标签: c# multithreading sockets locking

过去48小时内,我一直在尝试了解MultithreadingSocket Programming。我尝试实现套接字编程,并在不使用多线程时取得了成功。我是这两个主题的新手,并且已经在堆栈上提出了2-3个问题,需要帮助。

经过Google搜索后,我找到了解释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线程如何工作?什么事情同时发生?

我对所有这些问题感到困惑

我知道这里有一个问题列表,但是如果你能帮助我理解使用多线程的方法,那将是一个很大的帮助。

3 个答案:

答案 0 :(得分:2)

connection.Thread.Start(connection)启动一个新线程,调用ProcessConnection,将connection作为state参数传递。在新线程中执行ProcessConnection时,当前线程中的执行会立即继续执行下一行。

ProcessConnectionSocket传递给它的ConnectionInfo对象获取AcceptConnections对象,并等待从套接字接收数据。当它接收数据时,它会遍历ConnectionInfo集合中的所有其他connections个对象,并按顺序将这些数据发送给每个对象。

那么这里同时运行的是什么?好吧,我们有一个初始线程(称之为线程0)在无限循环中执行AcceptConnections。然后对于我们接受的每个套接字连接,我们有一个执行ProcessConnection的线程。

需要锁定,因为ProcessConnection使用foreach循环已知连接以向其发送数据。如果在foreach中枚举集合时,线程0要向集合添加新连接,则InvalidOperationException中将抛出ProcessConnection

lock确实可以防止这种情况下的并发问题,但它也会导致潜在的性能问题。它不仅阻止AcceptConnectionsProcessConnection枚举时修改集合。它还可以防止执行ProcessConnection的任何两个线程同时枚举集合。在这种情况下,更好的选择是ReaderWriterLockSlim,它允许多个线程同时读取集合。

答案 1 :(得分:1)

我假设_connectionsList<ConnectionInfo>:列表不是线程安全的,并且此线程将项添加到该列表中。如果另一个线程同时删除一个项目,结果将是不可预测的。所以你必须确保没有其他进程可以使用锁来访问它。

connection.Thread.Start(connection);启动一个新的线程,它将立即启动或很快启动。当前线程(您在此处看到的代码)将无法对其进行任何控制。这个新线程虽然提供了ConnectionInfo对象,但它将知道在哪个套接字上执行任务。当前线程一直在监听新客户端,ProcessConnection函数将处理最近接受的客户端。

答案 2 :(得分:1)

在C#中,我认为在CLR中,每个对象可能都与monitor相关联。这里_connections是一个集合,可能与从这个函数启动的线程共享(它们可能在完成后从集合中删除连接)。默认情况下,C#中的集合不会同步,您必须明确地执行此操作,因此lock(_connections)语句可以阻止集合上的races