c++ - 当永远不会同时访问共享托管对象时,在生产者和消费者之间使用 std::shared_ptr 是否安全?

标签 c++ thread-safety c++14 shared-ptr smart-pointers

下面是演示代码片段。 由于 std::shared_ptr 本身是线程安全的并且托管对象永远不会被生产者和消费者同时访问,因此可以删除 mutex 吗?

#include <memory>
#include <mutex>
#include <thread>

struct Demo {
    int i;
    float f;
};

using SCDemoPtr = std::shared_ptr<Demo>;

class ResultManager {
public:
    ResultManager();
    void SetFrontRes(SCDemoPtr oms_result);
    void SetBackRes(SCDemoPtr oms_result);
    void MergeResults();

private:
    std::mutex front_mutex;
    std::mutex back_mutex;
    SCDemoPtr front_result;
    SCDemoPtr back_result;
};

ResultManager::ResultManager() {}

void ResultManager::SetFrontRes(SCDemoPtr oms_res) {
    std::lock_guard<std::mutex> guard(front_mutex);
    front_result = oms_res;
}

void ResultManager::SetBackRes(SCDemoPtr oms_res) {
    std::lock_guard<std::mutex> guard(back_mutex);
    back_result = oms_res;
}

void ResultManager::MergeResults() {
    SCDemoPtr cur_front_res;
    SCDemoPtr cur_back_res;

    {
        std::lock_guard<std::mutex> guard(front_mutex);
        cur_front_res = front_result;
    }

    {
        std::lock_guard<std::mutex> guard(back_mutex);
        cur_back_res = back_result;
    }

    if (cur_front_res == nullptr || cur_back_res == nullptr) {
        return;
    }

    SCDemoPtr merge_res(new Demo);
    merge_res->i = cur_front_res->i + cur_back_res->i;
}

int main() {
    ResultManager res_manager;

    std::thread producer1([&res_manager]() {
        while (true) {
            SCDemoPtr res(new Demo);
            res->i = 1;
            res->f = 3.14;
            res_manager.SetFrontRes(res);
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    });

    std::thread producer2([&res_manager]() {
        while (true) {
            SCDemoPtr res(new Demo);
            res->i = 1;
            res->f = 3.14;
            res_manager.SetBackRes(res);
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    });

    while (true) {
        res_manager.MergeResults();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    producer1.join();
    producer2.join();

    return 0;
}

最佳答案

Could the mutex be removed since std::shared_ptr itself is thread-safe

不,对 std::shared_ptr 本身的访问不是线程安全的,并且与访问任何其他对象的行为没有任何不同。当另一个线程尝试访问它时尝试修改它会导致数据竞争并导致未定义的行为。

对于 std::shared_ptr 来说,唯一的事情是托管对象的生命周期,它保证被一个线程销毁。

关于c++ - 当永远不会同时访问共享托管对象时,在生产者和消费者之间使用 std::shared_ptr 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77253184/

相关文章:

c++ - 是否可以在编译时读取文件?

c++ - 减少 float 平方和的舍入误差

c++ - Boost 以自定义方式序列化数据

c++ - 访问器和修改器方法

java - 非servlet类的实例变量是线程安全的吗?

java - Tomcat内部是如何创建线程的?

c++ - 静态库中带有外部模板的 undefined symbol

c++ - 如何知道它是文本中的新行

java - 以下实用程序类是线程安全的吗?

c++ - 通用 lambda 与标准模板函数(使用什么以及何时使用)