c++ - 正确锁定从多个线程调用其自己的成员函数的类。 (我需要锁定访问 "this"指针吗?)

标签 c++ multithreading c++11 locking valgrind

我正在编写一个多线程应用程序,它目前有一个生成线程的类,然后从这些线程中调用它自己的成员函数。我认为只要成员函数本身不使用任何共享资源就可以,但是当我使用 --tool=helgrind 选项运行 valgrind 来检测它提示的数据竞争和其他与线程相关的问题。

foo_main.cpp:

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

class Foo final
{
public:
    void DoSomething() const
    {
        std::thread t1([&] {
            // Do I need to lock before accessing "this"?
            // std::lock_guard<std::mutex> lock(m_mutex);
            this->Print();
        });

        std::thread t2([&] {
            // Do I need to lock before accessing "this"?
            // std::lock_guard<std::mutex> lock(m_mutex);
            this->Print();
        });

        t1.join();
        t2.join();
    }
private:
    void Print() const
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        std::cout << "TEST" << std::endl;
    }

    mutable std::mutex m_mutex;
};

int main()
{
    Foo foo;
    foo.DoSomething();
}

这是 valgrind 的输出:

valgrind --tool=helgrind ./foo
==27751== Helgrind, a thread error detector
==27751== Copyright (C) 2007-2017, and GNU GPL'd, by OpenWorks LLP et al.
==27751== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==27751== Command: ./foo
==27751==
TEST
==27751== ---Thread-Announcement------------------------------------------
==27751==
==27751== Thread #1 is the program's root thread
==27751==
==27751== ---Thread-Announcement------------------------------------------
==27751==
==27751== Thread #2 was created
==27751==    at 0x7848ACE: clone (in /usr/lib64/libc-2.17.so)
==27751==    by 0x5051059: do_clone.constprop.4 (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x5052569: pthread_create@@GLIBC_2.2.5 (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x4C355BE: pthread_create_WRK (hg_intercepts.c:445)
==27751==    by 0x4C36A9B: pthread_create@* (hg_intercepts.c:478)
==27751==    by 0x531B596: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x401C94: thread<Foo::DoSomething() const::__lambda0> (thread:135)
==27751==    by 0x401C94: Foo::DoSomething() const (foo_main.cpp:14)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== ----------------------------------------------------------------
==27751==
==27751== Possible data race during write of size 8 at 0xA6A6E18 by thread #1
==27751== Locks held: none
==27751==    at 0x4018FA: ~_Impl_base (thread:97)
==27751==    by 0x4018FA: std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> >::~_Impl() (thread:107)
==27751==    by 0x401508: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (new_allocator.h:124)
==27751==    by 0x401508: _S_destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (alloc_traits.h:281)
==27751==    by 0x401508: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (alloc_traits.h:405)
==27751==    by 0x401508: std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27751==    by 0x401CD0: _M_release (shared_ptr_base.h:144)
==27751==    by 0x401CD0: ~__shared_count (shared_ptr_base.h:546)
==27751==    by 0x401CD0: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x401CD0: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x401CD0: thread<Foo::DoSomething() const::__lambda0> (thread:135)
==27751==    by 0x401CD0: Foo::DoSomething() const (foo_main.cpp:14)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== This conflicts with a previous read of size 8 by thread #2
==27751== Locks held: none
==27751==    at 0x531B316: ??? (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x4C357B2: mythread_wrapper (hg_intercepts.c:406)
==27751==    by 0x5051EA4: start_thread (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x7848B0C: clone (in /usr/lib64/libc-2.17.so)
==27751==  Address 0xa6a6e18 is 24 bytes inside a block of size 56 alloc'd
==27751==    at 0x4C2D7B8: operator new(unsigned long) (vg_replace_malloc.c:422)
==27751==    by 0x401BEF: allocate (new_allocator.h:104)
==27751==    by 0x401BEF: allocate (alloc_traits.h:351)
==27751==    by 0x401BEF: __shared_count<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr_base.h:499)
==27751==    by 0x401BEF: __shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr_base.h:957)
==27751==    by 0x401BEF: shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:316)
==27751==    by 0x401BEF: allocate_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:598)
==27751==    by 0x401BEF: make_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:614)
==27751==    by 0x401BEF: _M_make_routine<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (thread:193)
==27751==    by 0x401BEF: thread<Foo::DoSomething() const::__lambda0> (thread:135)
==27751==    by 0x401BEF: Foo::DoSomething() const (foo_main.cpp:14)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==  Block was alloc'd by thread #1
==27751==
==27751== ----------------------------------------------------------------
==27751==
==27751== Possible data race during read of size 8 at 0xA6A6E28 by thread #1
==27751== Locks held: none
==27751==    at 0x4018FD: ~__shared_count (shared_ptr_base.h:545)
==27751==    by 0x4018FD: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x4018FD: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x4018FD: ~_Impl_base (thread:97)
==27751==    by 0x4018FD: std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> >::~_Impl() (thread:107)
==27751==    by 0x401508: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (new_allocator.h:124)
==27751==    by 0x401508: _S_destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (alloc_traits.h:281)
==27751==    by 0x401508: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > > (alloc_traits.h:405)
==27751==    by 0x401508: std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#1} ()> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27751==    by 0x401CD0: _M_release (shared_ptr_base.h:144)
==27751==    by 0x401CD0: ~__shared_count (shared_ptr_base.h:546)
==27751==    by 0x401CD0: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x401CD0: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x401CD0: thread<Foo::DoSomething() const::__lambda0> (thread:135)
==27751==    by 0x401CD0: Foo::DoSomething() const (foo_main.cpp:14)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== This conflicts with a previous write of size 8 by thread #2
==27751== Locks held: none
==27751==    at 0x531B325: ??? (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x4C357B2: mythread_wrapper (hg_intercepts.c:406)
==27751==    by 0x5051EA4: start_thread (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x7848B0C: clone (in /usr/lib64/libc-2.17.so)
==27751==  Address 0xa6a6e28 is 40 bytes inside a block of size 56 alloc'd
==27751==    at 0x4C2D7B8: operator new(unsigned long) (vg_replace_malloc.c:422)
==27751==    by 0x401BEF: allocate (new_allocator.h:104)
==27751==    by 0x401BEF: allocate (alloc_traits.h:351)
==27751==    by 0x401BEF: __shared_count<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr_base.h:499)
==27751==    by 0x401BEF: __shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr_base.h:957)
==27751==    by 0x401BEF: shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:316)
==27751==    by 0x401BEF: allocate_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:598)
==27751==    by 0x401BEF: make_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> >, std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (shared_ptr.h:614)
==27751==    by 0x401BEF: _M_make_routine<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > (thread:193)
==27751==    by 0x401BEF: thread<Foo::DoSomething() const::__lambda0> (thread:135)
==27751==    by 0x401BEF: Foo::DoSomething() const (foo_main.cpp:14)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==  Block was alloc'd by thread #1
==27751==
TEST
==27751== ---Thread-Announcement------------------------------------------
==27751==
==27751== Thread #3 was created
==27751==    at 0x7848ACE: clone (in /usr/lib64/libc-2.17.so)
==27751==    by 0x5051059: do_clone.constprop.4 (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x5052569: pthread_create@@GLIBC_2.2.5 (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x4C355BE: pthread_create_WRK (hg_intercepts.c:445)
==27751==    by 0x4C36A9B: pthread_create@* (hg_intercepts.c:478)
==27751==    by 0x531B596: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x401E96: thread<Foo::DoSomething() const::__lambda1> (thread:135)
==27751==    by 0x401E96: Foo::DoSomething() const (foo_main.cpp:20)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== ----------------------------------------------------------------
==27751==
==27751== Possible data race during write of size 8 at 0xA6A6E18 by thread #1
==27751== Locks held: none
==27751==    at 0x40187C: ~_Impl_base (thread:97)
==27751==    by 0x40187C: std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> >::~_Impl() (thread:107)
==27751==    by 0x4014E6: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (new_allocator.h:124)
==27751==    by 0x4014E6: _S_destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (alloc_traits.h:281)
==27751==    by 0x4014E6: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (alloc_traits.h:405)
==27751==    by 0x4014E6: std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27751==    by 0x401ED5: _M_release (shared_ptr_base.h:144)
==27751==    by 0x401ED5: ~__shared_count (shared_ptr_base.h:546)
==27751==    by 0x401ED5: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x401ED5: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x401ED5: thread<Foo::DoSomething() const::__lambda1> (thread:135)
==27751==    by 0x401ED5: Foo::DoSomething() const (foo_main.cpp:20)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== This conflicts with a previous read of size 8 by thread #3
==27751== Locks held: none
==27751==    at 0x531B316: ??? (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x4C357B2: mythread_wrapper (hg_intercepts.c:406)
==27751==    by 0x5051EA4: start_thread (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x7848B0C: clone (in /usr/lib64/libc-2.17.so)
==27751==  Address 0xa6a6e18 is 24 bytes inside a block of size 56 alloc'd
==27751==    at 0x4C2D7B8: operator new(unsigned long) (vg_replace_malloc.c:422)
==27751==    by 0x401DAF: allocate (new_allocator.h:104)
==27751==    by 0x401DAF: allocate (alloc_traits.h:351)
==27751==    by 0x401DAF: __shared_count<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr_base.h:499)
==27751==    by 0x401DAF: __shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr_base.h:957)
==27751==    by 0x401DAF: shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:316)
==27751==    by 0x401DAF: allocate_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:598)
==27751==    by 0x401DAF: make_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:614)
==27751==    by 0x401DAF: _M_make_routine<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (thread:193)
==27751==    by 0x401DAF: thread<Foo::DoSomething() const::__lambda1> (thread:135)
==27751==    by 0x401DAF: Foo::DoSomething() const (foo_main.cpp:20)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==  Block was alloc'd by thread #1
==27751==
==27751== ----------------------------------------------------------------
==27751==
==27751== Possible data race during read of size 8 at 0xA6A6E28 by thread #1
==27751== Locks held: none
==27751==    at 0x40187F: ~__shared_count (shared_ptr_base.h:545)
==27751==    by 0x40187F: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x40187F: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x40187F: ~_Impl_base (thread:97)
==27751==    by 0x40187F: std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> >::~_Impl() (thread:107)
==27751==    by 0x4014E6: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (new_allocator.h:124)
==27751==    by 0x4014E6: _S_destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (alloc_traits.h:281)
==27751==    by 0x4014E6: destroy<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > > (alloc_traits.h:405)
==27751==    by 0x4014E6: std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::{lambda()#2} ()> > >, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27751==    by 0x401ED5: _M_release (shared_ptr_base.h:144)
==27751==    by 0x401ED5: ~__shared_count (shared_ptr_base.h:546)
==27751==    by 0x401ED5: ~__shared_ptr (shared_ptr_base.h:781)
==27751==    by 0x401ED5: ~shared_ptr (shared_ptr.h:93)
==27751==    by 0x401ED5: thread<Foo::DoSomething() const::__lambda1> (thread:135)
==27751==    by 0x401ED5: Foo::DoSomething() const (foo_main.cpp:20)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==
==27751== This conflicts with a previous write of size 8 by thread #3
==27751== Locks held: none
==27751==    at 0x531B325: ??? (in /usr/lib64/libstdc++.so.6.0.19)
==27751==    by 0x4C357B2: mythread_wrapper (hg_intercepts.c:406)
==27751==    by 0x5051EA4: start_thread (in /usr/lib64/libpthread-2.17.so)
==27751==    by 0x7848B0C: clone (in /usr/lib64/libc-2.17.so)
==27751==  Address 0xa6a6e28 is 40 bytes inside a block of size 56 alloc'd
==27751==    at 0x4C2D7B8: operator new(unsigned long) (vg_replace_malloc.c:422)
==27751==    by 0x401DAF: allocate (new_allocator.h:104)
==27751==    by 0x401DAF: allocate (alloc_traits.h:351)
==27751==    by 0x401DAF: __shared_count<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr_base.h:499)
==27751==    by 0x401DAF: __shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr_base.h:957)
==27751==    by 0x401DAF: shared_ptr<std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:316)
==27751==    by 0x401DAF: allocate_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:598)
==27751==    by 0x401DAF: make_shared<std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> >, std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (shared_ptr.h:614)
==27751==    by 0x401DAF: _M_make_routine<std::_Bind_simple<Foo::DoSomething() const::__lambda1()> > (thread:193)
==27751==    by 0x401DAF: thread<Foo::DoSomething() const::__lambda1> (thread:135)
==27751==    by 0x401DAF: Foo::DoSomething() const (foo_main.cpp:20)
==27751==    by 0x401480: main (foo_main.cpp:38)
==27751==  Block was alloc'd by thread #1
==27751==
==27751==
==27751== Use --history-level=approx or =none to gain increased speed, at
==27751== the cost of reduced accuracy of conflicting-access information
==27751== For lists of detected and suppressed errors, rerun with: -s
==27751== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 9 from 8)

当从多个线程访问成员函数时,我是否总是需要在尝试通过“this”指针访问之前锁定?因为它是一个 const 成员函数,所以它不会修改对象本身,所以我认为不会有问题,但是 valgrind 仍然给我很多警告.

在实际应用程序中,我处理线程调用的成员函数会做很多事情,因此将代码移出成员函数并将其复制到我使用它的任何地方并不是一个真正的选择。但是在调用函数之前锁定会带来问题,因为函数中的很多内容可以并发完成,并且阻止不使用共享资源的函数部分并发运行会显着降低应用程序的速度。

最佳答案

这看起来确实有点像 libstdc++ 中的旧错误。这是我得到的输出。

==27663== This conflicts with a previous read of size 8 by thread #3
==27663== Locks held: none
==27663==    at 0x4AD9056: ??? (in /usr/lib64/libstdc++.so.6.0.19)
==27663==    by 0x40394FD: mythread_wrapper (hg_intercepts.c:406)
==27663==    by 0x524ADD4: start_thread (in /usr/lib64/libpthread-2.17.so)
==27663==    by 0x555CEAC: clone (in /usr/lib64/libc-2.17.so)

这看起来像是对内存的原始读取。我没有 libstdc++ debuginfo,所以我不知道“???”在哪里是。调用堆栈在新线程中,所以我猜它是 libstdc++ 准备调用 lambda。

回到 main,对于 std::thread 的创建和关闭,我看到 libstc++ 已经从使用 std::shared_ptr 切换到 std::unique_ptr。

我很确定 libstdc++ 代码是

   b5048:       eb d3                   jmp    b501d <_ZNSt11this_thread11__sleep_forENSt6chrono8durationIlSt5ratioILl1ELl1EEEENS1_IlS2_ILl1ELl1000000000EEEE@@GLIBCXX_3.4.18+0x16d>
   b504a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

Entry point here:
   b5050:       55                      push   %rbp
   b5051:       53                      push   %rbx
   b5052:       48 83 ec 08             sub    $0x8,%rsp

Error here:
   b5056:       48 8b 07                mov    (%rdi),%rax
   b5059:       48 8b 5f 10             mov    0x10(%rdi),%rbx
   b505d:       48 c7 47 08 00 00 00    movq   $0x0,0x8(%rdi)
   b5064:       00
   b5065:       48 c7 47 10 00 00 00    movq   $0x0,0x10(%rdi)
   b506c:       00
   b506d:       ff 50 10                call   *0x10(%rax)
   b5070:       48 85 db                test   %rbx,%rbx
   b5073:       74 20                   je     b5095 <_ZNSt11this_thread11__sleep_forENSt6chrono8durationIlSt5ratioILl1ELl1EEEENS1_IlS2_ILl1ELl1000000000EEEE@@GLIBCXX_3.4.18+0x1e5>

指针是:

(gdb) p this
$80 = (std::thread::_Impl<std::_Bind_simple<Foo::DoSomething() const::__lambda0()> > * const) 0x582c058

这是实现 std::thread 内部状态实现的模板类。

关于c++ - 正确锁定从多个线程调用其自己的成员函数的类。 (我需要锁定访问 "this"指针吗?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72731875/

相关文章:

c++ - 如何仅在定义时才调用 C++11 模板中的函数

c++ - C++ 数组初始化的 Doxygen 问题

c++ - 如何将文件中的数据输入到 C++ 中的矩阵中?

multithreading - 确保只有一个服务实例在 Clojure 中运行/启动/停止的规范方法?

python - 线程启动后如何更改其特性?

c++ - 使用用户定义的转换运算符的函数模板重载决议

c++ - g++ C++0x 枚举类编译器警告

C++ 动态线程

c++ - 根据 C++ 中的用户输入更改模板类型

java - 如何jUnit测试另一个线程中代码的结果