multithreading - 哈希和数组的推送和弹出操作是原子的和线程安全的吗?

标签 multithreading hash push semaphore raku

我有一个需要处理的巨大数据文件(接近 4T)。我在我的 4 核 CPU 上使用 4 个线程。第一个线程分析文件的第一季度,依此类推。所有线程在分析完自己四分之一的数据文件的部分后,都需要将其结果添加到相同的单个哈希和单个数组中。那么,哈希和数组的“push”、“pop”、“shift”和“unshift”操作是原子的和线程安全的,还是我不得不求助于信号量等更复杂的机制?

最佳答案

不,它们既不是原子的也不是线程安全的,多线程使用会导致崩溃或数据不一致。

也就是说,即使是这样,在同一数据结构上涉及大量争用的设计也会随着您添加更多线程而难以扩展。这是因为硬件在面对并行性时的工作方式;简要地:

  • 内存性能在很大程度上取决于缓存
  • 一些高速缓存级别是每个 CPU 内核
  • 写入内存意味着将其独占到当前内核的缓存中
  • 将其从一个内核的缓存中移动以写入它的过程是昂贵的(ballpack 60-100 周期惩罚)

  • 您可以使用锁定来获得正确性。为此,我不建议直接使用锁,而是查看像 OO::Monitors 这样的模块。 ,您可以在其中将散列封装在一个对象中并在边界处完成锁定。

    如果与生成要推送的项目所做的工作量相比,您在共享数据结构上执行的推送次数较少,那么您可能不会在数据结构周围的锁定和争用上成为瓶颈。如果您正在做成千上万的 push es 或类似的每秒,但是,我建议寻找替代设计。例如:
  • 将工作分解为每个 worker 的一部分
  • 使用start触发每个 worker ,返回 Promise .把 Promise s 成一个数组。
  • 有每个Promise返回它产生的项目的数组或散列。
  • 合并每个结果。例如,如果 each 返回一个数组,则 my @all-results = flat await @promises;或类似的足以将所有结果收集在一起。

  • 您可能会发现您的问题非常适合 parallel iterator paradigm, using hyper or race ,在这种情况下,您甚至不需要拆分工作或自己设置 worker ;相反,您可以选择学位和批量大小。

    关于multithreading - 哈希和数组的推送和弹出操作是原子的和线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61354013/

    相关文章:

    java - 在 Swing 事件中启动线程

    python - 为什么顺序代码比多线程代码快?

    ruby - 增加散列中的值

    javascript - 使用 Javascript 将地址栏中的哈希值替换为斜杠

    ios - iOS 推送通知

    c - 使用 fork() 时收割子进程

    ruby - 如何合并两个哈希而不丢失值

    尝试推送到远程分支时出现git错误

    mercurial - MVN 发布 :prepare with Mercurial push FAIL

    c# - AsyncWaitHandle.WaitOne 会阻塞 CLR 线程吗?或者它是否创建一个 I/O 完成端口?