YARV 数组的 push/pop 方法是线程安全的吗?
Are YARV Arrays' push/pop methods thread-safe?
假设我有一对(生产者、消费者)YARV 线程(Tp
、Tc
)共享一个 Array
q
- Tp
推送到 q
,Tc
从中弹出。如果压入和弹出的执行顺序不重要,代码是否可以在没有任何同步机制的情况下工作?
由于其全局解释器锁 (GIL),大多数时候访问数组在 MRI/YARV 中是线程安全的(并且仅在那里),因此大多数情况下是偶然的。
您仍然必须确保每次只执行一个操作并避免 read/write 构造。在其他 Ruby 实现中,如 Rubinius 或 JRuby,数组显然不是线程安全的。
话虽如此,Ruby 附带了一个不同的线程间通信原语,巧合的是 MRI/VARV 中唯一的 class 是明确的线程-安全: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 的维护良好的项目,它为跨线程的并发编程提供了许多强大的原语。
假设我有一对(生产者、消费者)YARV 线程(Tp
、Tc
)共享一个 Array
q
- Tp
推送到 q
,Tc
从中弹出。如果压入和弹出的执行顺序不重要,代码是否可以在没有任何同步机制的情况下工作?
由于其全局解释器锁 (GIL),大多数时候访问数组在 MRI/YARV 中是线程安全的(并且仅在那里),因此大多数情况下是偶然的。
您仍然必须确保每次只执行一个操作并避免 read/write 构造。在其他 Ruby 实现中,如 Rubinius 或 JRuby,数组显然不是线程安全的。
话虽如此,Ruby 附带了一个不同的线程间通信原语,巧合的是 MRI/VARV 中唯一的 class 是明确的线程-安全: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 的维护良好的项目,它为跨线程的并发编程提供了许多强大的原语。