提问者:小点点

Cpp线程对象和shared_ptr问题


当我在这里阅读cppreference中的文档时,https://en.cppreference.com/W/cpp/memory/shared_ptr#示例

我想知道打印出来的第一个lp.use_count()可能的值是什么?我用“在输出内容中。

#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <mutex>
 
struct Base
{
    Base() { std::cout << "  Base::Base()\n"; }
    // Note: non-virtual destructor is OK here
    ~Base() { std::cout << "  Base::~Base()\n"; }
};
 
struct Derived: public Base
{
    Derived() { std::cout << "  Derived::Derived()\n"; }
    ~Derived() { std::cout << "  Derived::~Derived()\n"; }
};
 
void thr(std::shared_ptr<Base> p)
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::shared_ptr<Base> lp = p; // thread-safe, even though the
                                  // shared use_count is incremented
    {
        static std::mutex io_mutex;
        std::lock_guard<std::mutex> lk(io_mutex);
        std::cout << "local pointer in a thread:\n"
                  << "  lp.get() = " << lp.get()
                  << ", lp.use_count() = " << lp.use_count() << '\n';
    }
}
 
int main()
{
    std::shared_ptr<Base> p = std::make_shared<Derived>();
 
    std::cout << "Created a shared Derived (as a pointer to Base)\n"
              << "  p.get() = " << p.get()
              << ", p.use_count() = " << p.use_count() << '\n';
    std::thread t1(thr, p), t2(thr, p), t3(thr, p);
    p.reset(); // release ownership from main
    std::cout << "Shared ownership between 3 threads and released\n"
              << "ownership from main:\n"
              << "  p.get() = " << p.get()
              << ", p.use_count() = " << p.use_count() << '\n';
    t1.join(); t2.join(); t3.join();
    std::cout << "All threads completed, the last one deleted Derived\n";
}

可能的输出:

Base::Base()
  Derived::Derived()
Created a shared Derived (as a pointer to Base)
  p.get() = 0x2299b30, p.use_count() = 1
Shared ownership between 3 threads and released
ownership from main:
  p.get() = 0, p.use_count() = 0
local pointer in a thread:
  lp.get() = 0x2299b30, lp.use_count() = 5   <<<<<<<< HERE <<<<<<
local pointer in a thread:
  lp.get() = 0x2299b30, lp.use_count() = 3
local pointer in a thread:
  lp.get() = 0x2299b30, lp.use_count() = 2
  Derived::~Derived()
  Base::~Base()
All threads completed, the last one deleted Derived

@user2452809的回答令人非常赞赏,它指出了use_count()的一个重要特性。

假设use_count()将返回一个精确的计数,那么答案是什么?


共2个答案

匿名用户

反正我也不会依赖这个值。

在多线程环境中,use_count返回的值是近似的(典型的实现使用memory_order_relaved加载)

有关详细信息,请查看参考:https://en.cppreference.com/W/cpp/memory/shared_ptr/use_count

匿名用户

我认为它可能是{4,5,6}的一个值。我说的对吗?

问:为什么大于3?

答:打印时,至少调用一个thr函数。包括主函数中的引用。use_count应为3。但是当一个线程休眠了一秒而另两个线程还没有构造时,就不可能了。另一方面,如果有两个线程完成,最后一个线程的use_count将为3。但由于打印范围中的线程互斥,它不会是第一行。

问:为什么少于7?

答:因为在子线程睡眠期间,主线程将运行p.reset()。一秒钟对CPU来说是相当长的时间。