C ++ 11线程安全队列 [英] C++11 thread-safe queue

查看:196
本文介绍了C ++ 11线程安全队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理的项目使用多个线程来处理文件集合.每个线程都可以将文件添加到要处理的文件列表中,因此我将线程安全队列(我认为是这样)放在一起.相关部分如下:

A project I'm working on uses multiple threads to do work on a collection of files. Each thread can add files to the list of files to be processed, so I put together (what I thought was) a thread-safe queue. Relevant portions follow:

// qMutex is a std::mutex intended to guard the queue
// populatedNotifier is a std::condition_variable intended to
//                   notify waiting threads of a new item in the queue

void FileQueue::enqueue(std::string&& filename)
{
    std::lock_guard<std::mutex> lock(qMutex);
    q.push(std::move(filename));

    // Notify anyone waiting for additional files that more have arrived
    populatedNotifier.notify_one();
}

std::string FileQueue::dequeue(const std::chrono::milliseconds& timeout)
{
    std::unique_lock<std::mutex> lock(qMutex);
    if (q.empty()) {
        if (populatedNotifier.wait_for(lock, timeout) == std::cv_status::no_timeout) {
            std::string ret = q.front();
            q.pop();
            return ret;
        }
        else {
            return std::string();
        }
    }
    else {
        std::string ret = q.front();
        q.pop();
        return ret;
    }
}

但是,我偶尔在if (...wait_for(lock, timeout) == std::cv_status::no_timeout) { }块中进行段错误检查,并且在gdb中进行检查表明由于队列为空而发生段错误.这怎么可能?据我了解,wait_for仅在收到通知后才返回cv_status::no_timeout,并且只有在FileQueue::enqueue刚刚将新项目推送到队列中之后,才会发生这种情况.

However, I am occasionally segfaulting inside the if (...wait_for(lock, timeout) == std::cv_status::no_timeout) { } block, and inspection in gdb indicates that the segfaults are occurring because the queue is empty. How is this possible? It was my understanding that wait_for only returns cv_status::no_timeout when it has been notified, and this should only happen after FileQueue::enqueue has just pushed a new item to the queue.

推荐答案

根据标准condition_variables,即使事件尚未发生,也可以进行虚假唤醒.如果发生虚假唤醒,即使未通知,它也会返回cv_status::no_timeout(因为它醒了而不是超时).正确的解决方案当然是在进行操作之前检查唤醒是否真正合法.

According to the standard condition_variables are allowed to wakeup spuriously, even if the event hasn't occured. In case of a spurious wakeup it will return cv_status::no_timeout (since it woke up instead of timing out), even though it hasn't been notified. The correct solution for this is of course to check if the wakeup was actually legit before proceding.

详细信息在标准§30.5.1[thread.condition.condvar]中指定:

The details are specified in the standard §30.5.1 [thread.condition.condvar]:

-当通过调用notify_one(),调用notify_all(),绝对超时(ab._time)指定的绝对超时(30.2.4)到期或虚假通知时,该函数将解除阻塞.

—The function will unblock when signaled by a call to notify_one(), a call to notify_all(), expiration of the absolute timeout (30.2.4) specified by abs_time, or spuriously.

...

返回:如果abs_time指定的绝对超时(30.2.4)已过期,则cv_status :: timeout,否则为cv_status :: no_timeout.

Returns: cv_status::timeout if the absolute timeout (30.2.4) specifiedby abs_time expired, other-ise cv_status::no_timeout.

这篇关于C ++ 11线程安全队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆