【问题标题】:C++ Access to vector from multiple threadsC++ 从多个线程访问向量
【发布时间】:2012-08-28 23:07:12
【问题描述】:

在我的程序中,我有一些线程正在运行。每个线程都有一个指向某个对象的指针(在我的程序中 - 向量)。并且每个线程都会修改向量。

有时我的程序会因段错误而失败。我认为它的发生是因为线程 A 开始对向量做一些事情,而线程 B 还没有完成对它的操作?是真的吗?

我应该如何解决它?线程同步?或者可以创建一个标志 VectorIsInUse 并在使用它时将此标志设置为 true?

【问题讨论】:

  • 您很可能需要使用互斥锁来保护写操作。请注意,即使您锁定写操作,迭代器和引用也可能会失效,因此没有完全安全的解决方案。最好不要从多个线程执行修改操作。
  • 您好,分段错误通常是由于访问了您的进程未保留的内存造成的。可能是您使用的东西实际上不是指针吗?否则,请查看:stackoverflow.com/questions/1099513/…
  • @juanchopanza - 不仅仅是写操作,所有操作。 对共享数据的每次访问都必须受到保护。
  • @PeteBecker 同意,并且某些访问(例如对容器或迭代器的元素的引用)无论如何您都无法真正保护......

标签: c++ multithreading synchronization segmentation-fault flags


【解决方案1】:

这就是为什么几乎每个提供线程的类库都具有同步原语,例如互斥锁/锁。您需要设置其中一个,并获取/释放对共享项的每个操作的锁定(读取和写入操作,因为您还需要防止在写入期间发生读取,而不仅仅是防止同时发生多个写入)。

【讨论】:

    【解决方案2】:

    vector 与所有 STL 容器一样,不是线程安全的。您必须自己明确管理同步。 std::mutexboost::mutex 可用于同步对 vector 的访问。

    不要使用标志,因为这不是线程安全的:

    • 线程A检查isInUse标志的值,它是false
    • 线程 A 被挂起
    • 线程 B 检查isInUse 标志的值,它是false
    • 线程 B 将 isInUse 设置为 true
    • 线程 B 被挂起
    • 线程 A 已恢复
    • 线程 A 仍然认为 isInUsefalse 并将其设置为 true
    • 线程 A 和线程 B 现在都可以访问 vector

    请注意,每个线程都必须在需要使用它的整个时间内锁定vector。这包括修改vector 和使用vector 的迭代器,因为如果它们引用的元素是erase()vector 经历内部重新分配,迭代器可能会失效。例如不要

    mtx.lock();
    std::vector<std::string>::iterator i = the_vector.begin();
    mtx.unlock();
    
    // 'i' can become invalid if the `vector` is modified.
    

    【讨论】:

    • 请注意迭代器和引用可能会失效,并且您无法使用互斥锁来防止这种情况发生。
    • @juanchopanza,是的。仍在更新中。
    • 很高兴。我完全误读了你的答案。我看到了代码示例,我就像“WHAAA EPIC FAIL!”。然后我就像“哦,等等。”。
    • 无论如何,在使用向量之前必须明确记住锁定互斥锁是非常不安全的,因为没有什么可以防止意外误用,也没有什么可以防止迭代器泄漏。 concurrent_vector 更安全。
    • @DeadMG,只有concurrent_vector 微软吗?
    【解决方案3】:

    如果您想要一个可以在多个线程中安全使用的容器,您需要使用专门为此目的设计的容器。标准容器的接口不是为并发变异或任何类型的并发而设计的,你不能只是在问题上加锁。

    您需要 TBB 或 PPL 之类的内容,其中包含 concurrent_vector

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多