2013-03-20 75 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