【问题标题】:Do We Need Add Lock To the Code of Recv/Send/Close For a Same Socket Among Threads我们是否需要在线程间同一个套接字的 Recv/Send/Close 代码中加锁
【发布时间】:2015-02-11 21:30:32
【问题描述】:

this 之类的帖子中,我知道在 linux 上,recv/send 函数是线程安全的,并且允许用户同时从不同的线程对同一个套接字进行操作。

虽然这不是一个好的设计,但在以下情况下,我想知道我们应该从用户级代码中做什么,以保持数据一致性和健康的运行状态: 有线程在同一个套接字上运行,第一个用于创建和关闭套接字,第二个用于读取套接字,最后一个用于发送套接字。查看伪代码

 struct SocketInfo
 {
      int SockFd;
      int SockType;
      queue<Packet*> RecvPacks;
 };

 map<int, SocketInfo*> gSocketInfoMap;
 pthread_mutex_t       gSocketsLock;

 //Thread1
 pthread_mutex_lock(&gSocketsLock);
 // get information for sock
 SocketInfo* info = gSocketInfoMap[sock];
 pthread_mutex_unlock(&gSocketsLock);

 close(sock);         // line-1
 .....


 //thread-2
 pthread_mutex_lock(&gSocketsLock);
 SocketInfo* info = gSocketInfoMap[sock];
 pthread_mutex_unlock(&gSocketsLock);

 recv(sock, buffer, sizeof(buffer));         // line-2
 .....

 //thread-3
 pthread_mutex_lock(&gSocketsLock);
 SocketInfo* info = gSocketInfoMap[sock];
 pthread_mutex_unlock(&gSocketsLock);

 send(sock, buffer, sizeof buffer);         // line-3
 .....

请问是否需要将Line-1、Line-2、Line-3移入gSocketsLock的保护范围内?为什么?

【问题讨论】:

    标签: c++ linux multithreading sockets


    【解决方案1】:

    正如链接的问题所述,套接字操作是线程安全的。在任何情况下,接收和发送数据都是独立的操作,不会相互干扰。

    显然,关闭正在读取和写入的套接字并不是一个好主意,但是将close() 放在关键部分并不能防止该错误。确保活动套接字不关闭或关闭的套接字不被访问的任何机制都比 OP 中显示的关键部分处于更高级别。

    如果一个线程关闭了另一个线程试图用于 I/O 的套接字,最坏的情况是 recv/send 调用将返回错误。

    简而言之:不,将套接字操作放在临界区不是一个好主意。它没有任何好处,并且不必要地增加了锁争用的可能性。

    【讨论】:

      猜你喜欢
      • 2011-03-19
      • 2014-11-19
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      相关资源
      最近更新 更多