STL矢量多线程

时间:2015-03-14 23:47:35

标签: c++ multithreading boost locking mutex

我有一个标准向量和多个线程。我正在使用以下代码在需要时锁定:

boost::mutex::scoped_lock lock(mutex);

这个工作正常,应用程序运行没有任何问题,但现在我为向量创建了一个小类,以使我的生活更轻松:

template <class T> class FVector
{
private:
    std::vector<T>          standard_vector;
    mutable boost::mutex    mutex;

public:
    typedef typename std::vector<T>::iterator  iterator;
    typedef typename std::vector<T>::size_type size_type;

    FVector(void)
    {

    }

    iterator begin(void)
    {
        boost::mutex::scoped_lock lock(mutex);
        return standard_vector.begin();
    }

    iterator end(void)
    {
        boost::mutex::scoped_lock lock(mutex);
        return standard_vector.end();
    }

    void push_back(T & item)
    {
        boost::mutex::scoped_lock lock(mutex);
        standard_vector.push_back(item);
    }

    void erase(iterator it)
    {
        boost::mutex::scoped_lock lock(mutex);
        standard_vector.erase(it);
    }
};

但遗憾的是它不起作用。我只是得到 xx.exe已经触发了断点。异常,这意味着锁和多个线程在同一时间尝试写入和读取有问题。

我正在使用以下代码进行测试:

#include <Windows.h>
#include <process.h>
#include "thread_safe_vector.h"

struct TValue
{
    int value;
};

FVector<TValue> vec_Safe;

boost::mutex testMutex;

void thread2(void* pArg)
{
    while (true)
    {
        //boost::mutex::scoped_lock lock(testMutex);

        for (FVector<TValue>::iterator it = vec_Safe.begin(); it != vec_Safe.end(); it++)
        {
            if (it->value == 5)
            {
                vec_Safe.erase(it);
                break;
            }
        }
    }
}

void thread1(void* pArg)
{
    while (true)
    {
        TValue value;
        value.value = 5;

        //boost::mutex::scoped_lock lock(testMutex);

        vec_Safe.push_back(value);
    }
}

void main(void)
{
    HANDLE hThreads[50];

    for (size_t i = 0; i < 50; i++)
    {
        hThreads[i] = (HANDLE)_beginthread(i % 2 == 0 ? thread1 : thread2, NULL, NULL);
    }

    system("pause");

    for (size_t i = 0; i < 50; i++)
    {
        TerminateThread(hThreads[i], 0);
    }
}

我绝对没有想法,我试着找出问题好几个小时......有什么我做错的吗?

1 个答案:

答案 0 :(得分:3)

通过将锁定向下移动到较低的抽象级别,您引入了数据竞争。

    for (FVector<TValue>::iterator it = vec_Safe.begin(); it != vec_Safe.end(); it++)

此处begin()end()都在锁定下执行,但比较并非如此。更糟糕的是:

    {
        if (it->value == 5)

取消引用陈旧的迭代器,其他一方修改了它。

更重要的是,任何重新分配操作都可以一举使所有迭代器无效。

您将始终必须锁定整个循环。如果循环体需要很长时间,你可以复制锁下的元素,然后再处理它们。

然而,在这种情况下,使用(lockfree)队列并将元素从共享队列拼接到本地队列以提高效率更为典型。