我正在编写一个多线程应用程序,它目前有一个生成线程的类,然后从这些线程中调用它自己的成员函数。我认为只要成员函数本身不使用任何共享资源就可以,但是当我使用 --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/