gpt4 book ai didi

Ruby 互斥体与 GIL

转载 作者:行者123 更新时间:2023-12-02 09:04:09 26 4
gpt4 key购买 nike

如果一个线程正在等待阻塞 I/O,Ruby 互斥体是否允许两个线程同时执行?

这是我对 GIL 如何用于 MRI 的理解。我很好奇互斥锁和 GIL 之间有什么区别吗?

最佳答案

是的,这有效。正因为如此,在 MRI 中使用线程实际上对于许多工作负载都是有用的,即使只有一个线程可以并发执行“代码”。

一个常见的示例是 Web 应用程序,例如 Rails 应用程序。在这里,您可以使用例如运行多个线程Puma 在单个进程中,每个进程处理一个请求。由于您经常在这里等待数据库,因此也可以执行不同的线程。这是有效的,因为数据库适配器(例如 mysql2pg)通过调用数据库来释放 GIL,并在回复到达后重新获取它并传递给来电者。

但是,使用互斥体,您可以确保某个代码块一次仅由一个线程执行。一个常见的例子是加法器:

class Adder
attr_reader :number

def initialize
@number = 0
end

def add(number)
new_number = @number
new_number = new_number + number
@number = new_number

# The above code is extremely verbose to show what's happening here.
# It is equivalent to
# @number += number
end
end

这里,Adder#add方法不是线程保存的。如果多个线程尝试同时添加数字,则一些更新将会丢失,因为该操作不是原子操作(而是由读取、操作和写入组成)。通过 add 周围的互斥体,您可以确保操作在一个线程中完成,并且共享数据结构得到一致更新。

作为一般建议,如果您正在读取或更新跨线程边界共享的任何数据,则应始终使用互斥体。为了确保正确性,您还应该严格控制哪些数据结构跨线程边界传递,并尽可能避免。

如果您仍然需要这个,concurrent-ruby gem 提供了一些线程安全的数据结构,可以帮助跨线程边界共享数据。

关于Ruby 互斥体与 GIL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60403209/

26 4 0