使用原子减少多线程 C++ 代码中的互斥锁数量

问题描述 投票:0回答:1

我的多线程代码有 3 个不同的部分,可以这样描述:

(1)不受互斥锁保护: 这部分代码仅对 local 和 thread_local 变量以及保证在多线程期间不会更改的全局变量进行工作。

(2)受shared_lock保护: 这部分可以访问但不能修改一堆全局数据结构

(3)受unique_lock保护: 这部分可以访问和修改(有时是破坏性的)一堆全局数据结构

我只有一个全局shared_mutex,它被锁锁定了。

一切正常,但我注意到我有很多地方看起来像这样

struct MyStruct {
  uint64_t counter;
  //some other fields
};

unordered_map<uint64_t, MyStruct> map;
shared_mutex mutex;

void someFunction(uint64_t id) {
  shared_lock lock(mutex);

  auto it = map.find(id);
  if(it == map.end()) return;
  MyStruct &s = it->second;
  
  uint64_t counterValue = s.counter;
  doSomeWork(counterValue);//old value of counter is used

  mutex.unlock_shared();
  mutex.lock();
  //if we don't find id in map, it means that s was deleted during lock transition
  //id is never reused for a different struct
  if(map.find(id) == map.end()) return;
  s.counter += 1;
  mutex.unlock();
  mutex.lock_shared();

  if(map.find(id) == map.end()) return;

  doSomeMoreWork();//counter is not used anymore
}

进行大量重新锁定来增加单个计数器似乎很浪费,所以我想将计数器更改为原子计数器并具有类似的内容:

struct MyStruct {
  atomic<uint64_t> counter;
  //some other fields
};

unordered_map<uint64_t, MyStruct> map;
shared_mutex mutex;

void someFunction(uint64_t id) {
  shared_lock lock(mutex);

  auto it = map.find(id);
  if(it == map.end()) return;
  MyStruct &s = it->second;
  
  uint64_t counterValue = s.counter.fetch_add(1);
  doSomeWork(counterValue);//old value of counter is used
  doSomeMoreWork();//counter is not used anymore
}

我没有原子方面的经验。这能正常工作吗?是否存在一些需要注意的潜在问题?我还可以为 fetch_add 提供一堆不同的内存顺序:

memory_order_relaxed
memory_order_consume
memory_order_acquire
memory_order_release
memory_order_acq_rel
memory_order_seq_cst

这里哪一个才是正确的?

c++ multithreading atomic
1个回答
0
投票

是的,您可以使用原子来实现此目的。 事实上,您甚至可以将

s.counter += 1
的旧语法保留为
std::atomic<std::uint64_t>
。 但是,这将使用
std::memory_order::seq_cst
,这可能超出您的需要。

选择哪种内存顺序

如果您唯一需要的是一个以原子方式递增的计数器,那么使用

std::memory_order::relaxed
就足够了。 但是,如有疑问,请选择
seq_cst
。 您需要哪种内存顺序取决于对原子执行的其他操作。 这始终是大局,您无法孤立地为一项操作做出决定。

© www.soinside.com 2019 - 2024. All rights reserved.