Ruby 单例类是否会在多线程应用程序中产生问题?

Ruby 单例类是否会在多线程应用程序中产生问题?,ruby,Ruby,这可能是过早的优化,也可能是过早的过度警告,但我避免在一些类上使用单线程,因为我担心将来我需要将我的应用程序作为多线程运行,而单线程会造成冲突和混乱。单例在Ruby中是否存在这个问题,或者是否存在某种内置的名称空间,以便当a类引用单例时,只返回同一线程上的单例 编辑:澄清这些是可观察的类,更新时会导致其他正在监视它们的类更新。我不确定这是否是线程安全的,但我知道现在我正在传递大量的可观察类,这有点烦人。它们看起来确实像是自然的单例类。所有未编写为线程安全的类在多线程环境中都会导致问题,无论它们是

这可能是过早的优化,也可能是过早的过度警告,但我避免在一些类上使用单线程,因为我担心将来我需要将我的应用程序作为多线程运行,而单线程会造成冲突和混乱。单例在Ruby中是否存在这个问题,或者是否存在某种内置的名称空间,以便当a类引用单例时,只返回同一线程上的单例


编辑:澄清这些是可观察的类,更新时会导致其他正在监视它们的类更新。我不确定这是否是线程安全的,但我知道现在我正在传递大量的可观察类,这有点烦人。它们看起来确实像是自然的单例类。

所有未编写为线程安全的类在多线程环境中都会导致问题,无论它们是否为单例

您的类是单例的事实可能会使问题变得更糟,因为它在默认情况下是共享的。每个线程不能有一个实例

如果单例状态为只读且不可变,则不会出现线程安全问题


如果修改了共享状态,您必须确保它是线程安全的。

虽然这似乎是一种情况,但确实需要
线程,并在文档中说明以下内容:

Klass.\u实例化?()-返回“实例”或nil。这个钩子 方法将调用Klass.instance()的第二个(或第n个)线程放在 等待循环。返回值表示成功完成或 第一次或更一般地说,电流提前终止 “实例化线程”


这有帮助吗?

下面是一个使singelton线程安全的示例。您必须将其视为具有状态(
@things
)且不是不可变(只读)的任何其他对象。getter和setter需要通过互斥访问内部状态

require'singleton'
类MyObject
包括独生子女
def初始化
@事物=[]
@mutex=mutex.new
结束
def添加(东西)

使用互斥锁{@things Shared scope(singleton或not)可能会在多线程应用程序中导致问题。^这!singleton ruby mixin本身是线程安全的,因为“所有线程中都有相同的实例,保证。”正如Michael Kohl所写。但是,保留“您的”Singleton实现线程安全是您的责任。Immutable my在这种情况下可能不够具体。它可能是一个只公开对数据的只读访问,但在下面修改其内部状态的类。如果它修改其内部状态,那么它就不是不可变的。我相信在方法中调用Mutex.new会在在Ruby 2.6.1中,两个线程可以开始同时初始化@mutex变量。增加一个数字并附加到一个数组似乎不会产生任何竞争条件。我尝试了不同数量的线程,但没有一个线程产生竞争条件。我在这个链接中遇到了相同的问题。
require 'singleton'

class MyObject
  include Singleton

  def initialize
    @things = []
    @mutex  = Mutex.new
  end

  def add(thing)
    with_mutex { @things << thing }   
  end

  def things
    with_mutex { @things }
  end

  def clear
    with_mutex { @things.clear }
  end

  def self.add(thing)
    instance.add(thing)
  end

  def self.things
    instance.things
  end

  def self.clear
    instance.clear
  end

  private

  def with_mutex
    @mutex.synchronize { yield }
  end
end