【问题标题】:thread safe std::queue class c++17线程安全的 std::queue 类 c++17
【发布时间】:2021-08-10 18:27:11
【问题描述】:

queue_safe.cpp

#pragma once

#include <iostream>
#include <queue>
#include <string>
#include <mutex>
#include <condition_variable>
#include <chrono>

#include "queue_safe.h"

void SafeQueue::initialize() {

    /* initialize a std::queue */

    safe_queue = {};
    
}

std::string SafeQueue::get() {

    std::unique_lock<std::mutex> condition_lock(queue_lock);

    /* wait 20 seconds */

    std::chrono::system_clock::time_point wait = std::chrono::system_clock::now() + std::chrono::system_clock::duration(20);

    while (safe_queue.empty()) {

        if (ready.wait_until(condition_lock, wait) == std::cv_status::timeout) {

            /* timeout was reached, no items left */

            std::cout << "no items left in queue..." << std::endl;
        }

        std::string element = safe_queue.front();

        safe_queue.pop();

        return element;
    }

    /* not empty, return an element */
    
    std::string element = safe_queue.front();

    safe_queue.pop();

    return element;

}

void SafeQueue::put(std::string& element) {

    /* does not need to be thread-safe */

    safe_queue.push(element);

}

uint8_t SafeQueue::empty() {

    std::unique_lock<std::mutex> condition_lock(queue_lock);
    
    if (safe_queue.size() == 0) {
        return 1;
    }

    return 0;

}

queue_safe.h

#pragma once

#include <string>
#include <mutex>
#include <queue>
#include <condition_variable>

class SafeQueue {
public:
    std::condition_variable ready;
    std::mutex queue_lock;

    std::queue<std::string> safe_queue;
    uint8_t empty();
    void initialize();
    void put(std::string& element);
    std::string get();
};

这显示了我的代码可以安全地从队列中获取字符串。我想最多等待 20 秒以使元素可用,因此我使用条件变量、唯一锁,最后使用 wait_until。据我所知,我不需要围绕推送(添加)功能的互斥锁。 目标:创建一个线程安全队列,该队列在指定时间段(此处为 20 秒)后超时。
问题:这真的是线程安全的吗?我是否需要围绕推送功能使用互斥锁/保护,如果需要,为什么?
好的,所以 1)出于可读性目的,我需要使用 bool 而不是无符号整数,2)我需要同步推送和弹出,3)时间点并不是真正的 20 秒。 4) 我需要处理“虚假唤醒”

【问题讨论】:

  • std::chrono::system_clock::duration 总是代表秒吗?
  • 上面暗示std::chrono::system_clock::duration(20) 可能并不意味着“20 秒”。你的意思可能是std::chrono::seconds(20)
  • 是的,您绝对需要将您的push 与您的pop 同步。这两个都修改了队列,所以它们不能同时发生。
  • 请解释你为什么认为你"don't need a mutex around the push (add) function"
  • 当您在get 上超时时,您的函数将继续执行,就好像它没有超时并尝试弹出一个元素。这是一个编程错误。

标签: c++ queue thread-safety c++17


【解决方案1】:

据我所知,我不需要围绕推送(添加)函数的互斥锁。

你知道错了。

这真的是线程安全的吗?

没有。

我是否需要围绕推送功能设置互斥体/保护

是的。

为什么?

因为对容器的无序修改会导致未定义的行为。 std::queue::push 修改容器。

【讨论】:

  • 明白了,明白了解释
猜你喜欢
  • 2023-03-23
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2019-12-24
相关资源
最近更新 更多