Методы push / pop в YARV Arrays поточно-ориентированы?
Предположим, у меня есть пара (производитель, потребитель) потоков YARV (Tp
,Tc
) делиться Array
q
- Tp
подталкивает к q
, а также Tc
всплывает от этого. Если порядок выполнения нажатий и выталкиваний не имеет значения, работает ли код без какого-либо механизма синхронизации?
1 ответ
Доступ к массивам является поточно-ориентированным в MRI/YARV (и только там) в большинстве случаев из-за его глобальной блокировки интерпретатора (GIL), таким образом, в основном случайно.
Вам все равно придется убедиться, что вы выполняете только одну операцию каждый раз, и избегать конструкций чтения / записи. В других реализациях Ruby, таких как Rubinius или JRuby, массивы явно не безопасны для потоков.
С учетом вышесказанного, Ruby поставляется с другим примитивом для связи между потоками, который, кстати, является единственным классом в MRI/VARV, который явно ориентирован на многопоточность: Queue. Он поддерживает подталкивание и извлечение объектов в поточно-ориентированном виде.
Возьмите этот пример из документации Ruby:
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
Существует также хорошо поддерживаемый проект, называемый concurrent-ruby, который предлагает множество мощных примитивов для параллельного программирования между потоками.