我正在编写 C 扩展,提供 Ruby 和异步 I/O 库之间的接口(interface)。在我的代码上运行测试时,我经常遇到错误,包括(但不限于):
[BUG] cross-thread violation in rb_thread_schedule()
异步 IO 意味着我的 C 扩展需要从多个线程(不是主解释器线程)向 ruby 传递消息。我如何在此过程中避免这些线程安全冲突?
最佳答案
对于 ruby 1.8.x,避免该错误的唯一方法是显而易见的方法——仅从主解释器线程调用 Ruby/C API。我相信这也适用于 ruby 1.9.x,但我没有使用过它,也不知道它的 native 线程支持会如何改变事情。您不需要使用多个 native 线程直接调用 API,而是需要使用生产者/消费者模式将请求从次要 native 线程传递到主解释器线程中的代码。理想情况下,这样做不会不必要地阻塞其他 Ruby 绿色线程。如果您查看 ruby 实现,ruby 绿色线程调度程序本质上是一个 select()
循环。这表明以下总体结构:
- 创建管道或其他 IPC 机制,以提供真正的
select()
可用文件描述符。 - 生成 native 线程并为它们提供管道的写入端。
- 在主解释器线程中,进入一个事件循环,在管道的读取端调用
rb_thread_wait_fd()
。这将允许 ruby 绿色线程调度程序运行其他绿色线程。 - 当您的辅助 native 线程有对主线程的请求时,它们会将它们排队并写入管道,唤醒运行您的事件循环的绿色线程。
查看 rb_io_sysread()
(IO#sysread
的实现)可能是 ruby 代码库中最简单的干净 IO 使用函数。
关于c - 如何避免 Ruby 扩展中的跨线程冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3752006/