RubyでSingletonパターン考察1
スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 | 心
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般
お金 | 仕事 | 勉強 | プライベート | 健康 | 心
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般
Rubyでデザインパターンの一つである、Singletonパターンを考えてみる。
スポンサーリンク
単純なSingletonパターン
class Singleton
@@singleton = nil
# new をprivateにする
private_class_method(:new)
def self.singleton
if @@singleton == nil
@@singleton = new
end
return @@singleton
end
end
obj1 = Singleton.singleton
obj2 = Singleton.singleton
obj3 = Singleton.singleton
puts obj1.object_id
puts obj2.object_id
puts obj3.object_id
実行結果。
21102270 21102270 21102270
マルチスレッド実行での落とし穴がある
すべて3つともobject_idが等しく、Singletonが正しく動作しているように見えるが、一つだけ穴がありまして・・・
このコードは、マルチスレッドの場合に、複数のインスタンスが生成されてしまう可能性があります。
それは、以下の部分、
def self.singleton
if @@singleton == nil
@@singleton = new
end
return @@singleton
end
の、if 条件式と、newにより@@singletonにインスタンスが代入される間の部分。
現在のスレッドが@@singletonへのインスタンス代入を行おうとする直前に、スレッドが切り替わり、別のスレッドでのif 条件式の判定が行われた場合、複数のインスタンスが生成されてしまう可能性がある。
マルチスレッド実行時に複数インスタンスが生成されてしまう例
分かりやすいように、上記のif 条件式の後にsleepをはさんで、マルチスレッドで実行してみます。
class Singleton
@@singleton = nil
# new をprivateにする
private_class_method(:new)
def self.singleton
if @@singleton == nil
sleep 3
@@singleton = new
end
return @@singleton
end
end
puts "--- マルチスレッドの場合 ---"
threads = []
for i in 1..3
t = Thread.new do
obj = Singleton.singleton
puts "#{obj.object_id}\n"
end
threads << t
end
threads.each do |th|
th.join
end
実行結果。
--- マルチスレッドの場合 --- 21101870 21101830 21101790
object_idが変わってしまい、インスタンスが複数生成されてしまっています。
これでは、Singletonパターンになりません。
次回に、どう書けば、マルチスレッド対応のSingletonパターンになるか考察。
スポンサーリンク
>> 次の記事 : RubyでSingletonパターン考察2・マルチスレッド対応
スポンサーリンク