如何让一个线程等到所有其他人都完成阅读才能写入

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

操作系统:Windows 10编程语言:C ++

我写了一个程序,原本不是多线程的。现在我正在将它固定到多个线程上。

此时它全部围绕一个unordered_map,只有一个线程正在修改地图而所有其他线程只是读取。

所以基本上一次写多次读取。

到目前为止,我已经在写入中实现了mtx.lock和mtx.unlock,并且在写入过程发生时,没有人可以读取。

当有人在阅读时发生WRITE时会出现问题。

据我理解,理论上我可以在每次读取时使用相同的mtx.lock和mtx.unlock,这应该可以解决问题。但这是我迫切想要避免的事情,因为有很多要点读取数据并且我必须实现一百个或更多锁,这对我来说真的很不方便,因为对任何人来说都是如此。

我的问题是:我是否可以让正在进行写作的线程等到每个人都完成阅读,然后调用锁并进行写作。当然,如何才能做到这一点。

c++ multithreading
3个回答
1
投票

听起来你想要的基本上是一个读/写锁。这允许多个读者或单个编写者在任何时候都可以访问,但不能同时访问。

这可以通过使用std::shared_mutex在C ++ 17中实现,或者(对于较旧的C ++)通过使用boost::shared_mutex来实现。共享互斥锁允许两个级别的访问,可以是读者请求的共享访问,也可以是您想要写入时请求的独占访问。


0
投票

“我可以让正在写作的线程等到每个人都完成阅读,然后调用锁并进行写作吗?”

你问的解决方案与你想要实现的目标相反,因为你有多个阅读位置。每次阅读你都必须发送消息(锁定)。

一般来说听起来非常糟糕,但是:如果您的写入偶然发生,您可以向读取线程发送“锁定”消息。当你偶尔写时,阅读线程会收到一条消息/一个事件。然后读取线程会锁定片刻并发送消息(可以写入)写回线程。写完后写线程将通知读取线程可以读取。

Check this wiki page


0
投票

最简单的解决方案可能是std::atomic<std::unordered_map*>

读取时可以更新原子变量。您不能保证读者是获得旧指针还是新指针,但是它们将获得两个中的一个而不是随机值。

这很容易,但有一个缺点 - 你怎么知道什么时候delete你已经退休的旧地图是安全的?

还有另一种选择 - std::shared_ptr<std::unordered_map>。读者在阅读时会制作全局指针的私有副本。这可以确保他们使用的地图版本保持活动状态。编写器线程在有新映射时调用std::make_shared,并将其分配给全局指针。

std::shared_ptr足够线程安全。读取它是线程安全的,并且没有冲突的写入器(每个读取器线程都会覆盖它自己的副本。)

防爆。

class Writer {
  std::shared_ptr<std::unordered_map<Foo>> m_map;
  void add(Foo f) {
     auto copy = std::make_shared<std::unordered_map<Foo>>(m_map);
     copy.insert(f);
     m_map = foo; // thread-safe
  }
public:
  std::shared_ptr<std::unordered_map<Foo>> getMap() { return m_map; }
};
© www.soinside.com 2019 - 2024. All rights reserved.