Threadクラスでスレッド生成、およびMutexクラスでスレッドセーフな排他的アクセス
スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 | 心
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般
お金 | 仕事 | 勉強 | プライベート | 健康 | 心
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般
Rubyでのマルチスレッド操作を少し勉強しました。
Threadクラスでただ単にスレッドを生成して実行した場合、共有リソースへの並列アクセスで、共有リソースのデータ不整合など問題が起こる場合がある。
Mutexを用いると排他的アクセスを実現し、データの整合性を保つことができます。
以下、実験してみたコード。
スポンサーリンク
Thread単純実行、Threadを使わずループ、Mutexの3パターン
# スレッドのリストのうち、最初の3つを確認 def thread_list(threads) num = 0 threads.each do |t| p t num += 1 break if num == 3 end end # スレッドでの並列処理の場合、共有リソースへのアクセス時に注意する # Mutexを使うと排他処理になり、共有リソースへ安全にアクセスできる。 ThreadNum = 10000 puts "スレッドセーフでなく、共有リソースを破壊する例" class Count @@count = 0 def count_up @@count += 1 end def self.count return @@count end def self.count=(val) @@count = val end end puts Count.count threads = [] # スレッドをThreadNum個作って、配列に追加 for i in 1..ThreadNum t = Thread.new do Count.new.count_up end threads << t end # ThreadNum個のスレッド実行が終了するのを待つ。 for i in 1..ThreadNum threads[i - 1].join end # スレッドを確認 thread_list(threads) puts Count.count # ThreadNum個になるはずだが…足りない puts "--- スレッドを作らないで、単にループでカウントアップ ---" Count.count = 0 # countをリセット puts Count.count for i in 1..ThreadNum Count.new.count_up end puts Count.count # ThreadNum個になっている puts "--- Mutexを用いて、排他的アクセス ---" require 'thread' class CountByMutex @@count = 0 @@mutex = Mutex.new def count_up # mutexオブジェクトで排他的アクセスにする @@mutex.synchronize do @@count += 1 end end def self.count return @@count end end puts CountByMutex.count threads = [] # スレッドをThreadNum個作って、配列に追加 for i in 1..ThreadNum t = Thread.new do CountByMutex.new.count_up end threads << t end # ThreadNum個のスレッド実行が終了するのを待つ。 for i in 1..ThreadNum threads[i - 1].join end # スレッドを確認 thread_list(threads) puts CountByMutex.count # ThreadNum個になる
実行結果
スレッドセーフでなく、共有リソースを破壊する例 0 #<Thread:0x283e5a8 dead> #<Thread:0x283e558 dead> #<Thread:0x283e4f4 dead> 9940 --- スレッドを作らないで、単にループでカウントアップ --- 0 10000 --- Mutexを用いて、排他的アクセス --- 0 #<Thread:0x2afc4ac dead> #<Thread:0x2afc420 dead> #<Thread:0x2afc394 dead> 10000
排他制御の書き方は、こんな感じで良いのだろうか・・・(あんま自信ない)
Rubyの排他制御なメソッドの記述は、Javaのsynchronizedメソッドの書き方に少し似ています。
参考にしたページ:
逆引きRuby – スレッド
Thread – Rubyリファレンスマニュアル
第19章 スレッド(このページはムズイ・・・)
スポンサーリンク
スポンサーリンク