2012-07-05 84 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