在线程之间共享Ruby哈希并在每个线程中对其进行修改是否是线程安全的,并确保每个线程修改不同的密钥(在执行之前,在未确定的情况下将新的哈希附加到其密钥数目) ?
我知道,如果线程修改了相同的密钥,那么这样做不是线程安全的。但是,我不确定如果它们修改了不同的密钥是否安全。
例如下面是一个示例程序,可能说明了问题:
#!/usr/bin/env ruby
# frozen_string_literal: true
array = [*1..100]
hash = {}
array.each do |element|
hash[element] = {}
end
threads = []
array.each do |element|
threads << Thread.new do
random = rand(1..100)
hash_new_keys = [*0..random]
hash[element] = {}
hash_new_keys.each do |key|
hash[element][key] = rand(1..10)
end
end
end
threads.each(&:join)
答案 0 :(得分:3)
如果使用MRI,则其线程安全,可修改不同线程中的数组/哈希。 GIL保证同时只有一个线程处于活动状态。
这里有5个线程共享一个Array对象。每个线程将nil压入数组1000次:
array = []
5.times.map do
Thread.new do
1000.times do
array << nil
end
end
end.each(&:join)
puts array.size
$ ruby pushing_nil.rb
5000
$ jruby pushing_nil.rb
4446
$ rbx pushing_nil.rb
3088
由于MRI具有GIL,即使一次运行5个线程, 一次仅一个线程处于活动状态。换句话说,事情不是 真正的平行。 JRuby和Rubinius没有GIL,所以当您有 5个线程在运行,您实际上有5个线程在并行运行 跨可用核心。
在并行Ruby实现中,5个线程正在逐步执行 通过不是线程安全的代码。他们最终打断了每个人 其他,并最终破坏基础数据。
参考https://www.jstorimer.com/blogs/workingwithcode/8085491-nobody-understands-the-gil