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・マルチスレッド対応
スポンサーリンク