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

问题描述 投票:0回答:1

下面是演示代码片段。 由于

mutex
本身是线程安全的并且托管对象永远不会被生产者和消费者同时访问,因此是否可以删除
std::shared_ptr

#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; //could this mutex be removed since std::shared_ptr itself is thread_safe and the shared managed object would never be accessed by productor and consumer at the same time.
    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;

    {
        cur_front_res = front_result;
    }

    {
        std::lock_guard<std::mutex> guard(back_mutex);
        cur_back_res = back_result;
    }
    
    if(cur_back_res==nullptr || cur_back_res == nullptr)
    {
        return;
    }
    
    SCDemoPtr merge_res(new Demo);
    merge_res->i = cur_back_res->i + cur_back_res->i;
}

int main()
{
    ResultManager res_manager;
    std::thread([&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([&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));
    }
}
c++ thread-safety c++14 shared-ptr smart-pointers
1个回答
0
投票

由于 std::shared_ptr 本身是线程安全的,互斥锁是否可以被删除

不,对

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

只有是线程安全的,

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

© www.soinside.com 2019 - 2024. All rights reserved.