【问题标题】:STL vector multithreadingSTL 向量多线程
【发布时间】:2015-03-14 23:47:35
【问题描述】:

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

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);
    }
}

我完全没有想法,我试图找出问题几个小时......我做错了什么吗?

【问题讨论】:

    标签: c++ multithreading boost locking mutex


    【解决方案1】:

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

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

    这里begin()end() 都在锁定下执行,但比较没有。更糟糕的是:

        {
            if (it->value == 5)
    

    取消引用其他方修改过的陈旧迭代器。

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

    您将始终需要锁定整个循环。如果循环体花费大量时间,您可以复制锁下的元素,然后处理它们。

    但在这种情况下,更典型的做法是使用(无锁)队列并将共享队列中的元素拼接到本地队列以提高效率。

    【讨论】:

    • 感谢您的快速回答,所以看起来没有办法仅在“FVector”类中进行锁定?我想阻止自己在每个循环中添加锁。
    • @CsOkemf 不是你想的那样。您可以设计从其操作中返回可采用锁的 API,但根据我的经验,这种设计通常不是很清晰。
    • 嗯,谢谢。也许有什么你推荐使用的东西?
    • @CsOkemf 也许有,但很大程度上取决于应用程序的要求。我不建议在这里发布这样的问题。 Code ReviewSoftware Engineering 可能更热情好客
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多