libuv线程安全吗?

16 c++ pthreads node.js libuv

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

void thread_function()
{
  uv_loop_t *loop = uv_loop_new();
  uv_ref( loop );
  uv_run( loop );
}
Run Code Online (Sandbox Code Playgroud)

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

但是,在检查uv_ref源代码时,我没有看到任何保证在并发访问期间将同步对引用计数器变量的访问.另外,我没有看到在运行循环期间放弃对操作系统的控制的任何良率调用,这意味着程序将不能与其他进程很好地协作.

这让我相信我没有以正确的方式使用libuv.如果有人能解释我做错了什么,那就太好了!

小智 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);
}
Run Code Online (Sandbox Code Playgroud)

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

uv_async_send(&exit_handle);
Run Code Online (Sandbox Code Playgroud)

uv_async_send()在其他线程完成设置循环和uv_async句柄之前,您需要注意不要调用.最新版本的libuv包含您可以使用的uv_barrier同步原语; 但Node.js 0.8附带的libuv版本尚不支持,所以你可能需要使用pthread工具来完成这项工作.

在旁注中,您似乎在调用uv_refuv_unref使用循环引用作为参数.在最近的libuv版本中,这已经改变了,你现在应该uv_refuv_unref一个特定的句柄.有关详细信息,请参阅uv.h.