Я написал код в ruby для обработки элементов массива через threadpool. В этом процессе я предварительно выделил массив результатов, который имеет тот же размер, что и переданный массив. В threadpool я назначаю элементы в предварительно распределенном массиве, но индексы этих элементов гарантированно будут уникальными. Имея это в виду, мне нужно окружить задание Mutex#synchronize
?Является Ruby Array # [] = threadsafe для предварительно распределенного массива? Может ли это сделать беззаконным?
Пример:
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 этот код определен как безопасный?
Это зависит от того, какие реализации Ruby вы собираетесь использовать. MRI Ruby (классический) имеет глобальную блокировку интерпретатора. Я не думаю, что Ruby сам накладывает на это какие-либо гарантии, хотя я не могу дать хорошую цитату об этом (вот почему это не ответ). –