简体   繁体   English

Cpp 线程 object 和 shared_ptr 问题

[英]Cpp thread object and shared_ptr issue

When I read the document in cppreference here https://en.cppreference.com/w/cpp/memory/shared_ptr#Example当我在这里阅读 cppreference 中的文档时https://en.cppreference.com/w/cpp/memory/shared_ptr#Example

I am wondering what the possible value of the first lp.use_count() printed out is?我想知道打印出来的第一个lp.use_count()的可能值是多少? I marked it with "<<<<<" in output content.我在 output 内容中将其标记为“<<<<<”。

#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";
}

Possible output:可能的 output:

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 's answer is very appreciated, which pointed out an important feature of use_count() . @user2452809 的回答非常感谢,它指出了use_count()的一个重要特性。

Supposing use_count() would return an accurate count, what would be the answer?假设use_count()会返回一个准确的计数,答案是什么?

I wouldn't rely on that value anyway.无论如何,我不会依赖那个值。

In multithreaded environment, the value returned by use_count is approximate (typical implementations use a memory_order_relaxed load)在多线程环境中,use_count 返回的值是近似值(典型实现使用 memory_order_relaxed 加载)

Check the reference for more information: https://en.cppreference.com/w/cpp/memory/shared_ptr/use_count查看参考以获取更多信息: https://en.cppreference.com/w/cpp/memory/shared_ptr/use_count

I think it could be one value of {4,5,6}.我认为它可能是 {4,5,6} 的一个值。 Am I right?我对吗?

Q: Why larger than 3?问:为什么大于 3?

A: When printing, at least one thr function is invoked. A:打印时,至少调用一次thr Including the reference in main function.包括主 function 中的参考。 the use_count should be 3. But it's not possible when one thread sleep for one second and other two hadnot been constructed. use_count 应该是 3。但是当一个线程休眠一秒钟而另外两个尚未构造时,这是不可能的。 On the other hand, if there're two threads finished, the last thread would have a use_count 3. But it would not be the first line because of the thread mutex in printing scope.另一方面,如果有两个线程完成,最后一个线程的 use_count 为 3。但它不会是第一行,因为打印 scope 中的线程互斥锁。

Q: Why less than 7?问:为什么少于 7 个?

A: Because during the sleep in subthread, the main thread will run p.reset() . A:因为在子线程休眠期间,主线程会运行p.reset() One second is a quite long time to CPU.一秒钟对 CPU 来说是相当长的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM