libuv是否线程安全?

16

我创建了一个专门用于 libuv 循环的新线程。线程函数看起来像这样:

void thread_function()
{
  uv_loop_t *loop = uv_loop_new();
  uv_ref( loop );
  uv_run( loop );
}

通过增加引用计数器,线程能够保持存活状态并处理libuv事件。我希望通过在主线程上执行 uv_unref 来导致运行循环结束从而使线程退出。

然而,在检查 uv_ref 源代码时,我没有看到任何保证在并发访问期间对引用计数变量的访问将被同步。此外,在运行循环期间,我没有看到任何yield调用以放弃控制权给操作系统,这意味着程序将不会与其他进程很好地协作。

这让我相信我没有正确使用libuv。如果有人能解释一下我做错了什么,那就太好了!

1个回答

38

不,libuv在这方面不是线程安全的。您应该使用uv_async来发出退出循环的信号。uv_async是libuv唯一的线程安全设施。

它看起来会像这样:

uv_async_t exit_handle;

void exit_async_cb(uv_async_t* handle, int status) {
  /* After closing the async handle, it will no longer keep the loop alive. */
  uv_close((uv_handle_t*) &exit_handle, NULL);
}

void thread_function() {
  uv_loop_t *loop = uv_loop_new();
  /* The existence of the async handle will keep the loop alive. */
  uv_async_init(loop, &exit_handle, exit_async_cb);
  uv_run(loop);
}

现在,从另一个线程中,您可以通过调用此循环来发出退出信号

uv_async_send(&exit_handle);

在另一个线程完成设置循环和uv_async句柄之前,需要注意不要在调用uv_async_send()。libuv的最新版本包括可以使用的uv_barrier同步原语;但Node.js 0.8附带的libuv版本尚不支持这一点,因此您可能需要使用pthread工具来实现。

另外,您似乎正在使用循环引用作为参数调用uv_refuv_unref。在libuv的最近版本中,这已经改变了,现在应该使用特定的句柄进行uv_refuv_unref操作。有关详细信息,请参见uv.h


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