【问题标题】:Locking copy operation of std::shared_ptr inside lambda在 lambda 中锁定 std::shared_ptr 的复制操作
【发布时间】:2020-01-21 17:49:20
【问题描述】:

对于这个示例代码:

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

struct A
{
    int _i;
    A(int i):_i(i)
    {
        std::cout<<"A() "<<_i<<std::endl;
    }
    ~A()
    {
        std::cout<<"~A() "<<_i<<std::endl;
    }
    void Print()
    {
        std::cout<<"Print() "<<_i<<std::endl;
    }
};

struct B
{
    std::shared_ptr<A> Asp;
    std::mutex AspMutex;

    void SetA()
    {
        static int i = 0;
        std::unique_lock<std::mutex> lock(AspMutex);
        Asp = std::make_shared<A>(i);
    }

    void AccessA1()
    {
        std::shared_ptr<A> aspCopy;
        {
            std::unique_lock<std::mutex> lock(AspMutex);
            aspCopy = Asp;
        }
        (*aspCopy).Print();
    }

    void AccessA2()
    {
        auto aspCopy = [&]()
        {
            std::unique_lock<std::mutex> lock(AspMutex);
            return Asp;
        }();
        (*aspCopy).Print();
    }

    void AccessA3()
    {
        (*[&]()
        {
            std::unique_lock<std::mutex> lock(AspMutex);
            return Asp;
        }()
        ).Print();
    }

};

int main()
{
    B b;
    b.SetA();
    std::thread t([&]{b.SetA();});
    b.AccessA1();
    b.AccessA2();
    b.AccessA3();
    t.join();
}

我很好奇 c++17(或更高版本)标准是否会保证 A::Access1A::Access2 方法是线程安全的(std::shared_ptr 的副本将受 lock 保护)。

【问题讨论】:

  • 你能解释一下目前线程不安全的地方吗?因为您似乎在锁后访问Asp
  • 我不明白这个问题。你锁定,然后复制。为什么那不是线程安全的?
  • 编辑:没关系,我在std::thread之前错过了b.SetA()
  • @NicolBolas 据我所知没有。我只是好奇它是否会以任何方式危险。例如。 Access2 中的 Lambda 不能复制 shared_ptr 而是使用原始的等。

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


【解决方案1】:

是的。锁使A::Access1A::Access2 线程安全,并发SetA。在 C++17 中仍然如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2014-01-18
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多