首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby互斥对GIL

Ruby互斥对GIL
EN

Stack Overflow用户
提问于 2020-02-25 21:12:06
回答 2查看 349关注 0票数 2

如果一个线程等待阻塞I/O,Ruby互斥体允许两个线程并发执行吗?

这就是我对GIL在核磁共振成像中的作用的理解。我很好奇互斥和吉尔之间是否有什么区别?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-25 23:35:21

默认实现(MRI)上的全局解释器锁定(Global解释器Lock )阻止任何两个Ruby线程并发运行。Mutex阻止特定线程并发运行,其他线程可以任意运行。

注意,在没有GIL的实现中,规则是不同的,比如JRuby,线程可以独立和并发地运行。

实际上,Global解释器锁本身就是一个互斥锁,但它是默认使用的,而不是在代码中显式地使用,比如synchronize

如果一个线程在等待互斥对象时被阻塞,那么其他线程继续正常运行,它们能够独立地完成他们需要的任何事情。

全局解释器锁也不同,因为您的Ruby线程将被周期性地中断,以便其他线程能够运行。这是为了防止一个线程垄断锁。

票数 2
EN

Stack Overflow用户

发布于 2020-02-25 22:50:20

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

一个常见的例子是web应用程序,比如Rails应用程序。在这里,您可以在一个进程中运行多个线程,例如Puma,每个线程处理一个请求。因为您经常在这里等待数据库,所以也可以执行不同的线程。这是因为数据库适配器(例如mysql2pg)通过调用数据库释放GIL,并在应答到达并传递给调用方时重新获取它。

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

代码语言:javascript
复制
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周围的Mutex,您可以确保操作在一个线程中完成,并且共享数据结构得到一致更新。

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

如果您仍然需要这样做,并发红宝石 gem提供了一些线程安全的数据结构,可以帮助跨线程边界共享数据。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60403209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档