4

スレッドプールを介して配列内のアイテムを処理するコードを 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 の仕様では、このコードは安全と定義されていますか?

4

1 に答える 1