スレッドプールを介して配列内のアイテムを処理するコードを ruby で書きました。その過程で、渡された配列と同じサイズの結果配列を事前に割り当てました。スレッドプール内で、事前に割り当てられた配列にアイテムを割り当てていますが、それらのアイテムのインデックスは一意であることが保証されています。それを念頭に置いて、割り当てを ? で囲む必要がありMutex#synchronize
ますか?
例:
SIZE = 1000000000
def collect_via_threadpool(items, pool_count = 10)
processed_items = Array.new(items.count, nil)
index = -1
length = items.length
mutex = Mutex.new
items_mutex = Mutex.new
[pool_count, length, 50].min.times.collect do
Thread.start do
while (i = mutex.synchronize{index = index + 1}) < length do
processed_items[i] = yield(items[i])
# ^ do I need to synchronize around this? `processed_items` is preallocated
end
end
end.each(&:join)
processed_items
end
items = collect_via_threadpool(SIZE.times.to_a, 100) do |item|
item.to_s
end
raise unless items.size == SIZE
items.each_with_index do |item, index|
raise unless item.to_i == index
end
puts 'success'
(このテスト コードは実行に時間がかかりますが、毎回「成功」を出力しているように見えます。)
安全のために を で囲みたいと思いArray#[]=
ますMutex#synchronize
が、私の質問は次のとおりです。
Ruby の仕様では、このコードは安全と定義されていますか?