0

我有一个 SyncSet 模板类,它锁定了集合操作。当我在做压力测试时,我崩溃了。当我检查崩溃输出文件时,似乎原因是关于 set 容器的查找功能。您可以在下面看到我的模板类,您可以在 pastebin 链接中找到相关的崩溃输出:http: //pastebin.com/1JzAWxjf

我的模板类中是否有问题可能导致此类崩溃?其次,操作系统中止应用程序是否可能因为内存限制超过或类似的东西,那么有没有办法检查操作系统上的消息(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;
};
4

2 回答 2

2

您的代码不是线程安全的,因为尽管您保护了关键部分中对集合的所有写入,但您不保护 Has() 中的读取。

因此,例如,当另一个线程擦除整个集合时,压力测试可以在 Has() 调用的中途进行。

请注意,critical_Section 是一个门,仅在其他 EnterCriticalSection() 调用时才检查它,并且 Has 中的 find 不使用它,因此当另一个线程在临界区中时,那里的代码不会停止。

于 2013-03-20T22:41:26.233 回答
1

考虑设计一种不同类型的锁,以增加并行度。

让我们看一下我们当前正在做的事情以及我们因此被允许做的事情的表格:

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

只要没有其他线程正在写入,任何想要读取的线程都可以这样做,并且任何想要写入的线程只能在没有其他线程访问资源的情况下这样做。

请注意,如果没有此处未描述的一些额外工作,此解决方案将出现饥饿情况:尝试写入的线程可能必须等待很长时间才能完成所有读取线程,因为只要任何一个线程正在读取,写入线程将继续阻塞,但其他读取线程将能够获取它们的锁。

这对于您正在做的事情可能完全是矫枉过正,但如果您希望您的项目将充分分布,许多线程可能会尝试同时读取,那么它可能值得研究。我知道它不能直接回答您的问题,但是评论太长了,我认为它有可能有用。

于 2013-03-20T22:52:22.790 回答