クラスインスタンス変数がスレッドセーフかどうか疑問に思っています。最近、カスタム ORM のモデルによって引き起こされる d lock 問題に固執しました。(アクティブなレコードや続編モデルはありません。自分で作成した単純なバージョンの ORM です)。
シンプルにするために、ここではシンプルなバージョンをラップしました。
単純なクラス インスタンス変数を使用して、db インスタンス ( Sequel::Database オブジェクトの可能性があります) を保存します。
class TestORM
class << self
attr_accessor :db
def self.db=( db )
@db = db
end
end
end
そして、このデータベースがスレッドセーフかどうかを確認するためのテスト スクリプトを作成します。
require 'test_orm.rb'
t1 = Thread.new do
db = 'db string 1'
p "Thread 1: before assign, thread = #{Thread.current.object_id}, TestORM.db.object_id = #{TestORM.db.object_id}"
TestORM.db = db
p "Thread 1: after assign, thread = #{Thread.current.object_id}, TestORM.db.object_id = #{TestORM.db.object_id}"
sleep( 0.5 )
p "Thread 1: TestORM.db.object_id = #{TestORM.db.object_id}"
end
t2 = Thread.new do
db = 'db string 2'
p "Thread 2: before assign, thread = #{Thread.current.object_id}, TestORM.db.object_id = #{TestORM.db.object_id}"
TestORM.db = db
p "Thread 2: after assign, thread = #{Thread.current.object_id}, TestORM.db.object_id = #{TestORM.db.object_id}"
sleep( 0.5 )
p "Thread 2: TestORM.db.object_id = #{TestORM.db.object_id}"
end
t1.join
t2.join
上記のコードを実行すると、次の結果が生成されます。
"Thread 1: before assign, thread = 70332471940100, TestORM.db.object_id = 4"
"Thread 2: before assign, thread = 70332471939980, TestORM.db.object_id = 4"
"Thread 1: after assign, thread = 70332471940100, TestORM.db.object_id = 70332471939840"
"Thread 2: after assign, thread = 70332471939980, TestORM.db.object_id = 70332471939520"
"Thread 1: TestORM.db.object_id = 70332471939520"
"Thread 2: TestORM.db.object_id = 70332471939520"
上記の結果から、スレッド 2 がスレッド 1 の TestORM.db インスタンスをオーバーライドするため、クラス インスタンス変数はスレッド セーフではないようです。
この種のラッピングに関するヒントや解決策はありますか?
ルビーのバージョン: ルビー 1.9.2p320