2012-07-05 69 views
2
  1. 我有一个列表,其中一个线程只是push_back和其他线程偶尔遍历列表并打印所有元素。在这种情况下我需要锁吗?
  2. 我有指向其他对象中的元素的指针。有安全吗?我知道,当矢量需要更多空间时,矢量将移动所有对象,因此指针将失效。std :: list thread_safety

    mylist.push_back(MyObj(1));
    if(someCond)
    {
    _myLastObj = & mylist.back();
    }

_myLastObjMyObj*

如果我使用的载体的类型,所述对象将被移动到不同的位置和指针将指向垃圾。清单是否安全?

+0

它不是线程安全的。 1)。是的你应该! 2)我不明白。澄清一下。 – nullpotent 2012-07-05 09:55:04

+2

[我需要在多线程环境中保护对STL容器的读取权限吗?](http://stackoverflow.com/questions/187583/do-i-need-to-protect-read-access-to -an-stl-container-in-a-multithreading-environ) – 2012-07-05 10:00:34

+0

他也在事件中对它进行变异。没有笨蛋。 – Puppy 2012-07-05 10:55:04

回答

9
  1. 是的,你需要一个锁(某种形式的同步)。
  2. 指向std::list元素的指针仅在从列表中删除相同元素时才会失效。由于你的代码永远不会从列表中删除任何东西,你的指针是安全的。

为什么你需要的锁,例如考虑list::push_back允许做到以下几点,在此为了一个具体的理由:

  1. 分配一个新的节点,
  2. 设置“下“该列表的尾部指向新节点,
  3. 将新节点的”下一个“指针设置为空(或某个其他列表结束标记),则设置”先前“指针新节点到前一个尾部
  4. 将列表自己的指针设置为新节点。

如果您的读者线程在2到3之间,那么它将从前一个尾部到新节点,然后尝试遵循一个未初始化的指针。繁荣。

通常情况下,您需要同步,因为这是确保在编写器线程中所做的更改以任何合理顺序(或根本)发布到读者线程的唯一方法。

如果你想象不同的线程在不同的星球上运行,每个星球都有自己的程序存储器副本,并且相互之间发送更改(a),当你使用同步对象(或原子变量C++ 11),再加上(b)当你不使用同步对象,但传输某些特定的局部变化会破坏你的代码(比如一个两字对象的一半或者在这种情况下,你需要按照特定的顺序进行)。有时候这个模型比绝对必要的更保守,导致代码变慢。但是一个不太保守的模型依赖于线程系统和内存模型的具体实现细节。

+0

感谢您的解释。如果我使用boost :: slist并执行push_front?在这种情况下它是否安全,因为我不修改现有成员,因为它只会添加一个新节点并将下一个指向列表的开始位置? – balki 2012-07-05 10:11:51

+1

@balki:仍然不能保证安全。假设实现首先修改列表的指针指向新节点,然后修改新节点的下一个指针指向前一个头。如果你想通过Boost源代码并将其与你特定C++实现的内存模型进行比较(例如,缓存是连贯的),并且确信'boost :: s_list'目前没有这种类型,那么这就是你的调用。一般的答案是它是不安全的。如果你想要的是一个无锁队列,搜索一个,但是'list'和's_list'不是那个。 – 2012-07-05 10:13:11

+0

即使在std :: list情况下,如果序列是1,3,4,2,5。然后它看到新节点或看不到。会有中间状态吗?我同意如果多线程尝试push_back,这是一个问题,但在我的情况下,我确信只有一个线程将插入。 – balki 2012-07-05 10:17:06