使用 Ruby 并使用 Parallel 编写了以下代码和 JRuby 1.7.19 以加速从具有多个值的数组创建散列:
hash = {}
array = [
{"id" => "A001", "value" => 1},
{"id" => "B002", "value" => 0},
{"id" => "C003", "value" => 3},
{"id" => "D004", "value" => 0}]
Parallel.each(array, { in_threads: 5 }) do |item|
if keep_item?(item)
hash[item["id"]] = item
end
end
def keep_item?(item)
item["value"] > 0
end
我注意到在 Ruby 中并行地向散列添加键可能存在问题。此代码是否存在任何风险(线程安全、数据丢失、我不知道的奇怪锁等),以至于我应该将其作为常规系列 #each
调用保留?
最佳答案
Hash
不是线程安全的。如果 keep_item?
访问 hash
,就会出现竞争条件。即使没有,也会对 hash
进行并发更新,这很容易出错。
如果没有锁或其他同步,理论上无法保证对一个线程上的非线程安全 hash
的更新在另一个线程上可见。 hash
没有同步的并发更新可能会丢失数据,或者导致其他奇怪的问题。这取决于 Ruby Hash
的实现。
您的数据足够简单,只需使用普通的each
处理它们即可。如果您使用Parallel
,并为线程安全访问添加mutex/lock
,同步开销将显着增加整个过程的额外时间成本。安全并行版本可能会使用更多时间。
Parallel
在您的任务受 IO
限制或 CPU 限制时很有用,只要您有空闲内核并且任务不需要相互交换数据.
关于ruby - 在 Ruby 哈希中并行创建键值对的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31273868/