从源代码中可以看出,当您拨打电话zsocket_new
时,每个ZeroMQ套接字都会创建自己的内部线程(主要应用程序的天气是多线程的)。
这些内部线程正在运行select (0, &readfds, &writefds, &exceptfds, timeout ? &tv : NULL)
的循环(第167-173行,select.cpp)。
现在,我不明白的是,尽管有这些内部线程的可用性,为什么像zmq_msg_recv
这样的方法表现为阻塞调用,使你的主线程阻塞?
例如,请考虑以下代码
zctx_t *ctx = zctx_new();
void *router = zsocket_new(ctx, ZMQ_ROUTER);
int rc = zsocket_bind(router, "tcp://*:8080");
zframe_t *handle = zframe_recv(router);
它在你的调用线程上阻塞zframe_recv
,在signaler.cpp的第207--212行等待,执行int rc = select (0, &fds, NULL, NULL, timeout_ >= 0 ? &timeout : NULL)
换句话说,对于单个ZMQ套接字,您有两个线程执行两个select()操作!!
如果你想使zframe_recv
异步,你必须启动你自己的线程并在该线程内进行轮询或阻塞。
问题是 - 为什么ZMQ不使用这些内部线程进行选择,而不是强迫你创建另一个线程来读/写数据?
如果它只能适当地使用内部线程,它可能会成为一个非常好的演员模型 - 任何想法为什么它没有这样做?
答案 0 :(得分:0)
现在,我不明白的是,尽管有这些内部线程的可用性,为什么zmq_msg_recv之类的方法表现为阻塞调用,使你的主线程阻塞?
ZMQ鼓励拥有一组单线程节点的网络。每个节点都有一组套接字,用于与其他节点通信。节点上的ZMQ上下文管理跨线路的实际消息传输,并有自己的线程集合来执行此操作,但鼓励您的节点逻辑是单线程的。
这可以被描述为“反应式编程”。入站邮件是事件,您可以通过发送出站邮件来响应这些事件。当您致电zmq_msg_recv
或zmq_poll
时,意思是“等待下一个事件”并且正在阻止。
如果您发现无法使用单线程解决方案实现所需的节点逻辑,请考虑检查您的设计,以确保您的3线程节点不应该是3个单线程节点。