I wrote code in ruby to handle array elements through threadpool. In this process, I pre-allocated an array of results that is the same size as the passed array. In threadpool, I assign elements to a pre-allocated array, but the indices of these elements are guaranteed to be unique. With that in mind, do I need to surround the appointment with Mutex#synchronize?
Mutex#synchronize
Example:
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'
(This test code takes a lot of time, but each time it prints “success.”)
It seems I would like to surround Array#[]=with help Mutex#synchronizejust to be safe, but my question is:
Array#[]=
Does the Ruby specification specify this code as safe?
Ruby , Mutex (, , ). , , , .
Mutex
MRI Array.new(n, nil) , , , . , , .
Array.new(n, nil)
Array.new(n, nil) , , .
, ( , ), . , Ruby . , , , , , .