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章 スレッド(このページはムズイ・・・)
スポンサーリンク
スポンサーリンク