如何避免Ruby扩展中的跨线程违规?

时间:2010-09-20 13:39:58

标签: c ruby multithreading ruby-c-extension

我正在编写一个C扩展,提供Ruby和异步I / O库之间的接口。在对我的代码运行测试时,我经常会遇到错误,包括(但不限于):

[BUG] cross-thread violation in rb_thread_schedule()

异步IO意味着我的C扩展需要从多个线程(而不是主解释器线程)向ruby传递消息。如何避免这些线程安全违规?

1 个答案:

答案 0 :(得分:7)

对于ruby 1.8.x,避免错误的唯一方法是显而易见的 - 只从主解释器线程调用Ruby / C API。我相信这也适用于ruby 1.9.x,但我还没有使用它,也不知道它的原生线程支持如何改变它。您需要使用生产者/消费者模式将辅助本机线程的请求传递到主解释器线程中的代码,而不是让多个本机线程直接调用API。理想情况下,这样做不会不必要地阻止其他Ruby绿色线程。如果你看一下ruby实现,ruby green thread scheduler必须是一个select()循环。这表明了以下整体结构:

  • 创建一个管道或其他IPC机制,提供真正的select()文件描述符。
  • 生成本机线程并为它们提供管道的写入端。
  • 在主解释器线程中,输入一个事件循环,在管道的读取端调用rb_thread_wait_fd()。这将允许ruby green thread调度程序运行其他绿色线程。
  • 当您的辅助本机线程有主线程请求时,它们会将它们排队并写入管道,唤醒运行事件循环的绿色线程。

请参阅rb_io_sysread()IO#sysread的实现),了解ruby代码库中最简单的干净IO使用函数。