5

Rails プロジェクトに、インスタンス変数を設定する Ruby クラスがあるとします。

class Something
  def self.objects
    @objects ||= begin
      # some logic that builds an array, which is ultimately stored in @objects
    end
  end
end

@objects複数回設定できる可能性はありますか?begin1 つのリクエスト中に/上記の間でコードを実行している間に、endこのメソッドが 2 番目のリクエスト中に呼び出される可能性はありますか? これは、Rails サーバー インスタンスがどのようにフォークされるかという問題に帰結するのではないでしょうか。

代わりにMutexまたはスレッド同期を使用する必要がありますか? 例えば:

class Something
  def self.objects
    return @objects if @objects

    Thread.exclusive do
      @objects ||= begin
        # some logic that builds an array, which is ultimately stored in @objects
      end
    end
  end
end
4

2 に答える 2

7

MRI でも Rails をマルチスレッド モードで実行することは可能です (そして望ましいことです)。これは、 の行を変更することで実現できますproduction.rb

config.threadsafe!

MRI では、2 つのスレッドがコードを同時に実行することはできませんが、コンテキストの切り替えはいつでも発生する可能性があります。Rubinius と JRuby では、スレッドはコードを同時に実行できます。

あなたが示したコードを見てみましょう:

class Something
  def self.objects
    @objects ||= begin
      # some logic that builds an array, which is ultimately stored in @objects
    end
  end
end

コードは次の||=ように展開されます。

class Something
  def self.objects
    @objects || (@objects = begin
      # some logic that builds an array, which is ultimately stored in @objects
    end)
  end
end

これは、プロセスには実際には 2 つのステップがあることを意味します。

  1. 調べる@objects
  2. が偽の場合、式の結果に@objects設定されます@objectsbegin/end

コンテキストがこれらのステップ間で切り替わる可能性があります。ステップ 2 の途中でコンテキストが切り替わることは確かにあり得ます。これは、ブロックを 1 回ではなく複数回実行することになる可能性があることを意味します。MRI では、これは許容されるかもしれませんが、式の周りにミューテックスをロックするのは完全に簡単なので、そうしてください。

class Something
  MUTEX = Mutex.new

  def self.objects
    MUTEX.synchronize do
      @objects ||= begin
        # some logic that builds an array, which is ultimately stored in @objects
      end
    end
  end
end
于 2012-05-07T05:25:25.260 に答える
6

刺します。

Railsはシングルスレッドです。Railsアプリケーションへの連続したリクエストは、キューに入れられるか、個別のアプリケーションインスタンスによって処理されます(読み取り:プロセス)。@objectsクラスで定義されたクラスインスタンス変数の値は、Somethingアプリケーションのインスタンスのスコープ内ではなく、プロセスのスコープ内に存在します。

したがって、2つのプロセスのメモリスペースが完全に分離されているため、2つのプロセスが同じリソースにアクセスしている場合に遭遇することはないため、ミューテックスは不要です。

これは別の問題を提起すると思います@objects。共有リソースを意図しているので、別の方法で実装する必要があると思います。

免責事項:私はここで完全にマークから外れている可能性があります、実際、私は今日何かを学ぶことができるように私がそうなることを願っています:)

于 2012-05-01T04:40:28.613 に答える