2013-03-20 122 views
0

我有一個SyncSet模板類,它鎖定了set操作。當我做壓力測試時,我崩潰了。當我檢查崩潰輸出文件時,似乎原因是關於set容器的find函數。您可以在下面看到我的模板類,並且可以在pastebin鏈接中達到相關的崩潰輸出:http://pastebin.com/1JzAWxjf設置容器的find()發生崩潰

我的模板類中是否有錯誤可能導致此類崩潰?其次,操作系統中止應用程序是否可行,因爲內存限制超過或類似的東西,那麼是否有辦法檢查OS上的消息(Windows 7專業版)?

所有的建議和意見都是很好的和appricated。

謝謝。

template <typename T> 
class SyncSet 
{ 
public: 
    SyncSet() { 
     InitializeCriticalSection(&m_lock); 
    } 

    ~SyncSet() { 
     DeleteCriticalSection(&m_lock); 
    } 

    void Insert(T elem) { 
     EnterCriticalSection(&m_lock); 
     m_set.insert(elem); 
     LeaveCriticalSection(&m_lock); 
    } 

    bool Has(T elem) { 
     if (m_set.empty() || m_set.find(elem) == m_set.end()) 
      return false; 

     return true; 
    } 

    bool Erase(T elem) { 
     if (!Has(elem)) 
      return false; 
     EnterCriticalSection(&m_lock); 
     m_set.erase(elem); 
     LeaveCriticalSection(&m_lock); 
     return true; 
    } 

    size_t Size() { 
     return m_set.size(); 
    } 

    void Clear() { 
     EnterCriticalSection(&m_lock); 
     m_set.clear(); 
     LeaveCriticalSection(&m_lock); 
    } 

private: 
    std::set<T> m_set; 
    CRITICAL_SECTION m_lock; 
}; 
+2

當您對此進行壓力測試時,您能否談談您用於模板參數T的類?如果是這樣,請小心將它發佈在你的問題中?此外,這段代碼中有幾個地方應該傳遞const引用。最後,'Erase()'不需要檢查'Has()',如果使用多線程,'Has()'也應該用對象臨界區來守護。 – WhozCraig 2013-03-20 22:39:41

+0

您的測試是否爲多線程?如果是,那麼你應該在'Has'函數中鎖定/解鎖。順便說一句,你不需要檢查'空'在它 – borisbn 2013-03-20 22:43:51

+0

它是多線程。 Pastebin鏈接清楚地顯示了一個包含'ThreadFunc @ Thread @ CompanyInternal'的惡意調用堆棧。 – WhozCraig 2013-03-20 22:44:32

回答

2

您的代碼不是線程安全的,因爲雖然你保護的臨界區內所有寫一套,你不保護讀中有()。

例如,當另一個線程擦除整個集合時,壓力測試可以通過Has()調用的一半。

請注意,critical_Section是一個門,它僅在其他EnterCriticalSection()調用時被檢查,並且Has內的查找並未使用它,所以當另一個線程處於臨界區域內時,代碼將不會停止。

+0

感謝您的回覆,您是對的。 – mgundes 2013-03-21 07:18:38

1

考慮設計一種不同類型的鎖,以增加並行性。

讓我們看看目前我們正在做的事情的表,我們正在這樣允許這樣做:

     Trying to: 
        | Read | Write 
      --------|--------|---------- 
      Nothing | yes | yes 
Currently Reading | yes | no 
Doing:  Writing | no | no 

想要閱讀可以這樣做,只要任何線程,因爲沒有其他線程寫入,並且任何想要寫入的線程只有在沒有其他線程正在訪問資源時才能這樣做。

請注意,如果沒有在此處描述的某些額外工作,此解決方案將有一個飢餓條件:嘗試寫入的線程可能必須等待很長時間才能完成所有讀取線程,因爲只要任何一個線程正在讀取,寫入線程將繼續阻塞,但其他讀取器線程將能夠獲取它們的鎖定。

這可能對你正在做的事情完全過分,但如果你期望你的項目將被充分分發,許多線程可能會嘗試同時讀取,那麼可能值得研究。我明白它並不直接回答你的問題,但評論太長了,我認爲這有可能會有用。

+0

謝謝,這將是v1.0,下一步將是性能優化。那時我們也會考慮這個問題。 – mgundes 2013-03-21 08:29:14