Ruby 线程安全线程创建

标签 ruby multithreading concurrency thread-safety

我今天遇到了这段代码:

@thread ||= Thread.new do
  # this thread should only spin up once
end

它被多个线程调用。我担心如果多个线程正在调用此代码,您可能会创建多个线程,因为 @thread 访问不同步。但是,有人告诉我,由于全局解释器锁,这不可能发生。我阅读了一些有关 Ruby 中线程的内容,似乎运行 Ruby 代码的各个线程可能会被其他线程抢占。如果是这种情况,你不能有这样的交错:

Thread A             Thread B
========             ========
Read from @thread    .
Thread.New           .
[Thread A preempted] .
.                    Read from @thread
.                    Thread.New
.                    Write to @thread
Write to @thread

此外,由于对@thread 的访问不是同步的,因此对@thread 的写入是否保证对所有其他线程可见?我过去使用的其他语言的内存模型不能保证写入内存的可见性,除非您使用原子、互斥等同步对该内存的访问。

我仍在学习 Ruby,并且意识到要理解 Ruby 中的并发性还有很长的路要走。对此的任何帮助将不胜感激!

最佳答案

你需要一个互斥体。本质上,GIL 唯一保护你的是访问未初始化的内存。如果 Ruby 中的某些东西可以被明确定义而不是原子的,你不应该假设它是原子的。

一个简单的例子来说明你的例子排序是可能的。每次运行时我都会收到“double set”消息:

$global = nil
$thread = nil

threads = []

threads = Array.new(1000) do
  Thread.new do
    sleep 1
    $thread ||= Thread.new do
      if $global
        warn "double set!"
      else
        $global = true
      end
    end
  end
end

threads.each(&:join)

关于Ruby 线程安全线程创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57660980/

相关文章:

multithreading - Clojure:在多个 future 运行计算并不能加快我的程序

java - NIO 选择器 : How to properly register new channel while selecting

java - 斯卡拉 future : How to guarantee a non-null result?

Azure 数据库并发使用问题

ruby-on-rails - Rails for Zombies Lab 4 > 练习 3

c# - 为什么递归算法会添加重复文件?

ruby - Ruby 中优雅的日期解析

java - 这段代码对于java中的唯一id来说是线程安全的吗

ruby - 在 Fedora 15 上安装 ruby​​-1.8.7 时出错

ruby - ruby 中的深度限制 pp 或 to_yaml