ruby - 在 Ruby 哈希中并行创建键值对的问题

标签 ruby multithreading hash parallel-processing jruby

使用 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/

相关文章:

ruby-on-rails - FactoryGirl 记录未保存

Ruby:应该从子数组返回最大值数组的递归函数问题

c# - 我如何安全地锁定此属性?

java - 为什么此 Servlet 在其 "Thread Per Connection"策略中使用多个线程?

java - 一个Synchronized Collection Wrapper工厂方法是如何将 "own"对象传入其中的呢?

java - 仅根据 hashmap 的条件将值添加到键

ruby-on-rails - to_json 方法中的 Rails "wrong number of arguments (1 for 0)"

ruby-on-rails - rails +运动鞋 : could not obtain a connection from the pool

c# - 创建用于数据库的哈希码(即不使用 GetHashCode)

c - 如何从磁盘来回保存和加载一个巨大的哈希表?