当一个线程被阻塞时,其他线程会发生什么?

5
在Linux中,如果创建了两个线程并且它们都在运行,当其中一个调用recv()或任何IO系统调用时,如果没有数据可用,则整个进程会发生什么情况? 另一个线程会被阻塞吗?我想这取决于线程是如何实现的。如果线程库在用户空间中,内核完全不知道进程中的线程,则进程是调度实体,因此两个线程都会被阻塞。 此外,如果另一个线程由于此原因而不被阻塞,它是否可以通过同一套接字发送数据,该套接字正在阻塞recv线程?全双工?
有什么想法吗?
3个回答

2

阻塞调用在一个线程中不应影响其他线程。

如果被阻塞的线程在进入阻塞调用之前锁定互斥量,并且第二个线程试图锁定相同的互斥量,则第二个线程需要等待阻塞调用完成和第一个线程释放锁。


谢谢,然后进入第二个问题:当另一个非阻塞线程通过相同的套接字发送数据时,是否可以在另一个recv()阻塞时进行?假设使用UDP。 - Figo

2

完全可以在用户空间实现线程,以便一个线程可以在另一个线程阻塞I/O时继续执行。

未被阻塞的线程应该能够在另一个线程阻塞socket的同时发送数据(我已经编写了这样的代码)。


只有在系统调用支持非阻塞调用时才可能实现。在像fstat这样的操作上,很可能会使所有用户线程停滞数秒钟。 - Zan Lynx
@Zan Lynx:他在谈论 Linux,它具有符合 POSIX 标准的 aio_read() 和 aio_write() 系统调用。 - Steve Emmerson
你有注意到我说“像fstat吗?”那是一个没有异步版本的POSIX调用,据我所知。还有其他的。 - Zan Lynx

2
您说得很对,阻塞行为将取决于线程是在内核空间还是在用户空间中实现。如果线程完全在用户空间中实现(也就是说,内核与线程没有任何关系),那么任何进入内核的阻塞入口都需要用一些非阻塞变量进行包装,以模拟其调用“线程”的阻塞语义(例如使用AIO来发送/接收数据而不是阻塞,完成回调使线程再次运行)。
在Linux(以及我所知道的所有其他主要操作系统)中,线程是在内核级别或类似级别实现的,在内核中进行阻塞调用不会导致所有其他线程都被阻塞。
是的,您可以向另一个线程在recv()上阻塞的套接字发送send()

还有一个问题,如果在线程调用recv()之前套接字上有数据到达,那么线程会实际收到这些数据吗? - Figo
是的。这真的是唯一可行的方式,在非阻塞数据报套接字上。有几个小笔记,我希望对您有所帮助 - 首先,您可以很容易地尝试这种东西。编写一个小程序,将“accept”连接,然后“sleep”一段时间,然后在新连接上调用“recv”。使用“nc”(netcat)或其他工具创建到服务器的连接,并立即向其写入一些数据。您将看到服务器收到了与您发送的相同的数据。第二个注意点 - 这实际上是关于通常是一个一次问一个问题的论坛上的第三个不同的问题... - Aidan Cully

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接