6

我知道非阻塞接收在消息传递中的使用并不多,但仍然有一些直觉告诉我,它是必需的。以 GUI 事件驱动应用程序为例,您需要某种方式以非阻塞方式等待消息,以便您的程序可以执行一些计算。解决此问题的方法之一是使用带有消息队列的特殊线程。是否有一些用例,即使您有线程,您也确实需要非阻塞接收?

4

6 回答 6

4

线程的工作方式与非阻塞异步操作不同,尽管您通常可以通过使用执行同步操作的线程来实现相同的效果。然而,归根结底,它归结为如何更有效地处理事情。

线程是有限的资源,应该用于处理长时间运行的活动操作。如果你有一些不是很活跃的事情,但需要等待一段时间才能得到结果(想想网络上的一些 I/O 操作,比如调用 Web 服务或数据库服务器),那么最好使用提供的它的异步替代方案,而不是通过将同步调用放在另一个线程上来不必要地浪费线程。

您可以在此处详细阅读此问题以获得更多理解。

于 2010-04-23T02:45:52.480 回答
3

每个连接一个线程通常不是一个好主意(浪费内存,并非​​所有操作系统都非常适合具有大量线程数等)

你如何中断阻塞接收呼叫?例如,在 Linux 上(可能在其他一些 POSIX 操作系统上)pthreads + 信号 = 灾难。使用非阻塞接收,您可以多路复用接收套接字和用于线程之间通信的某种 IPC 套接字上的等待。也相对容易地映射到 Windows 世界。

如果您需要用更复杂的东西(例如 OpenSSL)替换常规套接字,则依赖阻塞行为可能会给您带来麻烦。例如,OpenSSL 可能会在阻塞套接字上死锁,因为 SSL 协议具有发送/接收反转的场景,在某些发送完成之前接收无法继续。

我的经验是——“当有疑问时使用非阻塞套接字”。

于 2010-04-23T03:14:08.757 回答
2

使用阻塞 IO,在许多平台上让您的应用程序在面对缓慢、挂起或断开连接的客户端/服务时尽最大努力有序关闭是一项挑战。

使用非阻塞 IO,您可以在系统调用返回后立即终止运行中的操作。如果您的代码是在考虑提前终止的情况下编写的 - 这对于非阻塞 IO 来说相对简单 - 这可以让您优雅地清理您保存的状态。

于 2010-04-28T23:57:40.573 回答
1

我想不出,但有时非阻塞 API 的设计方式比显式多线程实现更容易/更直观地使用。

于 2010-04-22T22:52:41.833 回答
1

这是我最近遇到的真实情况。以前我有一个每小时运行一次的脚本,由 crontab 管理,但有时用户会登录到机器并手动运行脚本。这有一些问题,例如 crontab 和用户的并发执行可能会导致问题,有时用户会以 root 身份登录 - 我知道,错误的模式,不受我的控制 - 并以错误的权限运行脚本。所以我们决定让例程作为守护进程运行,并具有适当的权限,并且用户之前运行的命令现在只会触发守护进程。

所以,这个用户执行的命令基本上会做两件事:触发守护进程并等待它完成任务。但它也需要超时,并在等待时继续将守护进程日志转储给用户。

如果我理解你提出的情况,我有你想要的情况:我需要在独立地与用户交互的同时继续监听守护进程。解决方案是异步读取。

对我来说幸运的是,我没有考虑过使用线程。如果我用 Java 编码,我可能会这样想,但这是 Python 代码。

于 2010-04-28T19:56:13.890 回答
0

我的观点是,当我们认为线程和消息传递是完美的时,真正的权衡是编写调度程序来规划非阻塞接收操作并为具有共享状态(锁等)的线程编写同步代码。我想说,两者都可能有时容易,有时困难。所以一个用例是当有许多消息要接收异步消息并且有很多数据要基于消息进行操作时。这在使用非阻塞接收的一个线程中非常容易,并且会要求与许多线程和共享状态进行大量同步......我也在考虑一些现实生活中的例子,我可能稍后会包含它。

于 2010-04-23T08:32:49.267 回答