首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用多线程、锁、套接字编程

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

Stack Overflow用户
提问于 2010-06-29 13:17:02
回答 3查看 1.8K关注 0票数 1

在过去的48小时里,我一直在努力理解MultithreadingSocket Programming。我试图实现套接字编程,并在不使用多线程时取得了成功。我对这两个主题都很陌生,并且对堆栈本身提出了2-3个问题,同样需要帮助。

在谷歌了很多之后,我找到了一个解释Socket ProgrammingMultithreadingSocket Programming,但是在这篇文章中我仍然有很多疑问,并且在文章中陷入了Figure 5

代码语言:javascript
复制
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是如何工作的?什么事情同时发生?

我被这些问题弄糊涂了

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-06-29 13:46:05

connection.Thread.Start(connection)通过调用ProcessConnection启动一个新线程,将connection作为state参数传递。当前线程中的执行将立即与下一行一起进行,而ProcessConnection将在新线程中执行。

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

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

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

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

票数 2
EN

Stack Overflow用户

发布于 2010-06-29 13:26:25

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

connection.Thread.Start(connection);将启动一个新线程,该线程将立即启动,或在不久的某个时候启动。当前线程(您在这里看到的代码)将无法控制它。不过,这个新线程提供了一个ConnectionInfo对象,因此它将知道在哪个套接字上执行任务。当当前线程不断侦听新客户机时,ProcessConnection函数将处理最近接受的客户端。

票数 1
EN

Stack Overflow用户

发布于 2010-06-29 13:31:52

在C#中,我认为在一般的CLR中,每个对象都可能有一个与它相关联的监控器。在这里,_connections是一个集合,可能与从这个函数启动的线程共享(它们可能在完成时从集合中删除连接)。默认情况下,C#中的集合不是同步的,您必须显式地执行它,因此必须使用lock(_connections)语句来防止集合上的种族

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3140965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档