13

Railsプロセス内にNeo4jグラフデータベースを埋め込むNeo4j.rb上で実行しているため、スレッド化されたRailsアプリを作成する必要があります。したがって、同じプロセスからの複数のリクエストを処理する必要があります。ええ、Neo4jデータベースへの接続がSQLデータベースのように機能するのは素晴らしいことですが、そうではないので、文句を言うのをやめて、それを使用します。

私は並行コードを書くことの意味についてかなり心配しています(私がそうあるべきです)、そして一般的な一般的なシナリオを処理する方法についてのアドバイスが必要です-コントローラーがインスタンス変数またはセッションハッシュの変数を設定し、次にいくつかのもの起こります。私が何を意味するかを示すために、次の大まかなコードを検討してください。

# THIS IS NOT REAL PRODUCTION CODE
# I don't do this in real life, it is just to help me ask my question, I
# know about one-way hashing, etc.!

class SessionsController
  def create
    user = User.find_by_email_and_password(params[:email], params[:password])
    raise 'auth error' unless user
    session[:current_user_id] = user.id
    redirect_to :controller => 'current_user', :action => 'show'
  end
end

class CurrentUserController
  def show
    @current_user = User.find(session[:current_user_id])
    render :action => :show # .html.erb file that uses @current_user
  end
end

質問:このコードに競合状態はありますか?

SessionsControllerでは、sessionハッシュとparamsハッシュはスレッドローカルですか?同じブラウザセッションが異なる資格情報を使用して/sessions#create(Railsルート構文を借用するため)に複数のリクエストを行うとすると、ログインしているユーザーはsession[:current_user_id] = user.id最後にラインに到達したリクエストである必要がありますか?または、コントローラーアクションの周りにミューテックスロックをラップする必要がありますか?

CurrentUserControllerで、異なるセッションの2つのリクエストが同時にshowアクションにヒットした場合、同じ@current_user変数が両方によって設定されますか?つまり、最初のリクエストは.html.erbファイルを処理しているときに、@ current_userインスタンス変数が2番目のスレッドによって突然変更されたことを検出しますか?

ありがとう

4

2 に答える 2

14

各リクエストは、コントローラーの新しいインスタンスを取得します。結果として、コントローラーのインスタンス変数はスレッドセーフです。paramsまたsession、コントローラー インスタンス変数 (または要求オブジェクト自体) によってサポートされるため、安全でもあります。

于 2012-08-17T10:25:30.017 に答える
3

スレッド間で何が共有され、何が共有されないかを知ることが重要です。

次に、特定の例に戻ります。2つのリクエストが同時にヒットCurrentUserController#showするため、2つの同時スレッドによって処理されます。ここで重要なのは、各スレッドが独自のインスタンスを持っているため、干渉しないCurrentUserController2つの変数があるということです。@current_userしたがって、の周りに競合状態はありません@current_user

競合状態の例は次のとおりです。

class ApplicationController < ActionController::Base
  before_each :set_current_user
  cattr_accessor :current_user

  def set_current_user
    self.class.current_user = User.find_by_id(session[:current_user_id])
  end
end

# model
class LogMessage < ActiveRecord::Base
  belongs_to :user

  def self.log_action(attrs)
    log_message = new(attrs)
    log_message.user = ApplicationController.current_user
    log_message.save
  end
end

より一般的な注意点として、GIL(Global Interpreter Lock)のため、MRIrubyでスレッドを使用することによるメリットはかなり限られています。GIL(jruby)を含まない実装があります。

于 2012-08-17T10:36:56.350 に答える