1. 程式人生 > >STL容器是執行緒不安全的----以及加鎖實現多執行緒訪問安全

STL容器是執行緒不安全的----以及加鎖實現多執行緒訪問安全

STL的執行緒安全. 說一些關於stl容器的執行緒安全相關的話題。

一般說來,stl對於多執行緒的支援僅限於下列兩點:(貌似Effective STL中有描述)

1.多個讀取者是安全的。即多個執行緒可以同時讀取一個容器中的內容。 即此時多個執行緒呼叫 容器的不涉及到寫的介面都可以 eg find, begin, end 等.

2.對不同容器的多個寫入者是安全的。即多個執行緒對不同容器的同時寫入合法。 但是對於同一容器當有執行緒寫,有執行緒讀時,如何保證正確? 需要程式設計師自己來控制,比如:執行緒A讀容器某一項時,執行緒B正在移除該項。這會導致一下無法預知的錯誤。 通常的解決方式是用開銷較小的臨界區(CRITICAL_SECTION)來做同步。以下列方式同步基本上可以做到執行緒安全的容器(就是在有寫操作的情況下仍能保證安全)。

  1.每次呼叫容器的成員函式的期間需要鎖定

  2.每個容器容器返回迭代器的生存期需要鎖定

  3.每個容器在呼叫演算法的執行期需要鎖定

  和小羅的關於task_server的多執行緒安全的交流: 是這樣的, 當你呼叫map的任何介面時, 比如 end(), begin(), find()等時, 可能會返回一個iterator, 如果有別的執行緒正在修改這個map, 你的iterator就變得無效了, 再用這個iterator行為就可能出問題. 或者在find()函式內部, 會訪問到map內部的紅黑樹的資料結構, 而這個紅黑樹是有可能被別的執行緒調整的(比如別的現在往map中插入一個不存在的記錄). 所以, 是危險的.

我們通常通過為容器加鎖來保證容器的執行緒安全性。

為容器加鎖

  • 多個讀取者是安全的。多執行緒可能同時讀取一個容器的內容,這將正確地執行。當然,在讀取時不能有任何寫入者操作這個容器。

  • 對不同容器的多個寫入者是安全的。多執行緒可以同時寫不同的容器。

針對容器的鎖實現

template<typename Container>
class Lock
{
public:
    Lock() =delete;
    Lock(const Container &container): c(container), released(false){
        getMutexFor(c);
    }
    ~Lock(){
        if(false == released){
            try{
                releaseMutexFor(c);
            }
            catch(...){

            }
        }
    }
    void releaseMutex(){
        releaseMutexFor(c);
        released = true;
    }
private:
    const Container &c;
    bool released;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27