多线程访问相同的deque C ++

时间:2016-03-25 21:16:52

标签: c++ multithreading

在我的多线程应用程序中,我有两个使用相同std::deque的线程。其中一个写入它,而另一个读取它(用于数据分析)。

我收到此错误:

  

Deque iterator not dereferencable

修改 这是我用来从双端队列中读取的代码。错误在if条件更深处被抛出(我在at访问双端队列的地方。)

for (int i = 0; i <myDeque.size(); i++){
    try{
        if (myDeque.at(i) > 10){
            //do stufff
        }
    }
    catch (...){
        cout << "ERROR" << endl;
    }
}

我认为,这是由于deque的多线程访问而发生的。 我无法通过try-catch块捕获错误。我不能这样做,因为它被扔进了更深的飞机&#34;? 有可能修复此错误吗?

2 个答案:

答案 0 :(得分:3)

以下是通过队列进行通信的读写器对的一个非常简单的示例。

请注意使用condition_variable来同步有关是否有工作要做以及编写器是否已完成的通信(表示读取器在清空队列时可以停止):

#include <iostream>
#include <thread>
#include <deque>
#include <condition_variable>

std::mutex m;
std::condition_variable reader_action;
bool all_written = false;

std::deque<int> buffer;

// note: this function is called with the mutex unlocked
// we have popped i from the buffer
void handle_read_event(int i)
{
    if (i % 100000 == 0)
        std::cout << i << std::endl;
}

int main()
{
    std::thread writer([]{
        for (int i = 0 ; i < 1000000 ; ++i)
        {
            {
                auto lock = std::unique_lock<std::mutex>(m);
                buffer.push_back(i);
                lock.unlock();
                reader_action.notify_one();
            }
        }

        auto lock = std::unique_lock<std::mutex>(m);
        all_written = true;
        lock.unlock();
        reader_action.notify_one();
    });

    std::thread reader([]{
        while(1)
        {
            auto lock = std::unique_lock<std::mutex>(m);
            reader_action.wait(lock, [] { return all_written || (!buffer.empty()); });
            if (!buffer.empty()) {
                int i = buffer.front();
                buffer.pop_front();
                lock.unlock();
                handle_read_event(i);
            }
            else if(all_written)
            {
                break;
            }
        }
    });

    writer.join();
    reader.join();
    return 0;
}

预期产出:

0
100000
200000
300000
400000
500000
600000
700000
800000
900000

如果我们决定在排除队列时不介意让编写器等待,我们可以实现第二个线程:

std::thread reader([]{
    while(1)
    {
        auto lock = std::unique_lock<std::mutex>(m);
        reader_action.wait(lock, [] { return all_written || (!buffer.empty()); });
        while (!buffer.empty()) {
            int i = buffer.front();
            buffer.pop_front();
            handle_read_event(i);
        }

        if(all_written)
        {
            break;
        }
    }
});

......或任何其他适合我们目的的策略。

答案 1 :(得分:2)

使用锁定?在一些常用的位置,声明mutex

... nondeque stuff ...
{
    std::lock_guard<std::mutex> lock(deque_lock);
    mydeque.push_back(...);
}
... more nondeque stuff...

然后将读取和写入包裹在blocks that acquire it中的... nondeque stuff ... { std::lock_guard<std::mutex> lock(deque_lock); for (const auto& elem : mydeque) { ... do stuff with each element, ideally cheap things to avoid blocking writer ... } } ... more nondeque stuff...

IEnumerator Fade(MeshRenderer myMesh)
{
    for (float t = 0f; t < FadeTime; t += Time.deltaTime)
    {
        float normalizedTime = t / FadeTime;

        _alpha = Mathf.Lerp(_startAlpha, _endAlpha, normalizedTime);
        // The fix
        myMesh.material.color = new Color (myMesh.material.color.r, myMesh.material.color.g, myMesh.material.color.b, _alpha);
        yield return null;
    }
    //_alpha = _endAlpha; 
    //myMesh.material.color = new Color (myMesh.material.color.r, myMesh.material.color.g, myMesh.material.color.b, _alpha);
}

阅读时:

{{1}}

尝试在锁定的块中将工作保持在最低限度;如果它是昂贵的工作,可能值得复制掉锁下的值,然后在没有锁的情况下使用它来避免阻塞其他线程。