概要
Single Threaded Execution
詳細
Single Threaded Executionは同時に一つのスレッドしか処理出来ないようなケースに
適用するパターンです。
Single Threaded Executionは別名Critical Section/Critical Regionとも呼ばれる。
サンプル仕様
ユーザーがロック式のバージョン管理ソフト「VisualSourceSafe」を利用することを想定します。
ユーザーはソースコードを編集するとユーザー名とソースコードをセットでVisualSourceSafeにコミットします。
この際、ユーザー名の登録とソースコードの登録の間には長い処理があると想定します。
各ユーザーは以下の様なコードを書きます
※#{user_name}部は各ユーザー名が入る
"hello #{user_name}"
サンプルUML
スレッドセーフではないパターン
# encoding: utf-8 require "pp" class VisualSourceSafe attr_accessor :source,:user def commit(user, source) @user = user sleep 1 @source = source end end class User attr_accessor :name def initialize(name) @name = name end def commit(vss, user, source) vss.commit user, source end end vss = VisualSourceSafe.new threads = %w[hoge hage hige].map do |user| Thread.new do |t| User.new(user).commit(vss, user, "hello #{user}") pp vss end end threads.each(&:join)
スレッドセーフではないパターンの出力
#<VisualSourceSafe:0x2945970 @source="hello hoge", @user="hige"> #<VisualSourceSafe:0x2945970 @source="hello hage", @user="hige"> #<VisualSourceSafe:0x2945970 @source="hello hige", @user="hige">
スレッドセーフなパターン(Single Threaded Executionパターン)
# encoding: utf-8 require "pp" require "thread" class VisualSourceSafe attr_accessor :source,:user def initialize @m = Mutex.new end def commit(user, source) @m.synchronize { @user = user sleep 1 @source = source } end end class User attr_accessor :name def initialize(name) @name = name end def commit(vss) vss.commit name, "hello #{name}" end end vss = VisualSourceSafe.new threads = %w[hoge hage hige].map do |user| Thread.new do |t| User.new(user).commit(vss) pp vss end end threads.each(&:join)
スレッドセーフなパターンの出力
#<VisualSourceSafe:0x28feb70 @m=#<Mutex:0x28feb40>, @source="hello hoge", @user="hoge"> #<VisualSourceSafe:0x28feb70 @m=#<Mutex:0x28feb40>, @source="hello hage", @user="hage"> #<VisualSourceSafe:0x28feb70 @m=#<Mutex:0x28feb40>, @source="hello hige", @user="hige"> [Finished in 3.1s]