【问题标题】:synchronizing access to allocated memory同步访问分配的内存
【发布时间】:2015-09-10 19:33:42
【问题描述】:

有没有办法同步访问分配的内存中的每个元素。例如,如果我使用以下代码分配内存

int* counters = new int[10];

有没有办法分别同步修改每个计数器(能够同时修改 counters[0]、counters[1]...counters[9])以便修改,比如说,counters[ 0] 不会阻塞 counters[9] 直到释放锁以更新 counters[9] 和其他计数器,而线程正在更新特定计数器 counters[0]?这些计数器不相关且不依赖于与其他计数器的任何共享数据?

【问题讨论】:

  • 使用互斥体数组。互斥数组中的索引对应于计数器数组中的索引。
  • 我想过,但是将分配的内存分页到磁盘会导致任何数据损坏。除了一组互斥体之外,还有其他标准方法来处理这种情况吗?
  • 如果分页对程序有任何可见的影响而不是性能,这将是一个非常严重的操作系统错误。
  • 你应该研究原子。如果您的“计数器”数组用于...计算每个数组元素是计数器的位置,只需将计数器设置为原子整数,您的增加和减少操作就可以有一个宽松的内存顺序。
  • 我会将计数器封装在一个类中,并提供访问器方法来获取/设置值,并在类内执行互斥。因此,该课程的用户甚至不必考虑同步。

标签: c++ multithreading locking mutex


【解决方案1】:

如果您想避免使用互斥锁进行同步,则需要查看 <atomic> 标头设施。

假设您的“计数器”数组只是一种跟踪一定数量的计数的方法,可以使用std::atomic<int> counters[10] 来完成,并且每个计数器都可以通过调用counters[i].fetch_add(1, std::memory_order_relaxed) 以线程安全的方式递增。

正如用户 Barmar 所指出的,std::atomic<int> 也可以在内部使用互斥锁。这取决于实现,可以通过调用std::atomic<int> 实例的is_lock_free() 成员函数来查询。在我的实现中,std::atomic<int> 实例是无锁的。

【讨论】:

  • 这不是很可能在幕后使用互斥锁吗?所以它可能会在互斥体的数量上遇到相同的限制?
  • 你是对的。我已经编辑了我的答案以明确这一点。
  • @Barmar,虽然有可能,但绝对不可能。
  • @SergeyA 我错误地认为互斥锁是确保原子性的最基本方法。
【解决方案2】:

虽然互斥体数组是一种自然的解决方案,但应该考虑其含义。这对于 10 个元素的数组来说很好,但互斥体的数量实际上是有限的。如果您有 50 000 个项目(根本没有那么大)的数组,您将用完互斥锁。

【讨论】:

  • 允许的最大互斥数是多少?
  • @user1886067 老实说 - 甚至在我的系统上都不知道,更不用说在你的系统上。
  • @SergeyA,你凭什么说有固定限制? POSIX 没有定义一个,实际上它小心地避免断言必须是一个,而不是适用于任何地方的可用系统资源的相同一般约束。
  • @JohnBollinger,您可以轻松检查您的系统)
  • @SergeyA,事实上,我不能。我能够证明我可以轻松地初始化 5,000,000 个互斥体,将它们全部锁定,全部解锁,然后全部销毁。我想我可以一直分配和初始化互斥锁,直到系统拒绝再创建,但我认为没有理由相信在我用完内存来存储它们之前会发生这种情况。
猜你喜欢
  • 1970-01-01
  • 2017-04-23
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 2021-03-16
  • 1970-01-01
  • 2013-08-22
相关资源
最近更新 更多