c++ 遞歸鎖的使用示例代碼
非遞歸鎖
同一個線程里,在鎖未釋放的情況下反復(fù)加鎖,會導(dǎo)致死鎖。
示例
#include <iostream> #include <mutex> #include <thread> #include <unistd.h> using namespace std; std::mutex m_mutex; void Func() { m_mutex.lock(); cout << "Func" << endl; m_mutex.unlock(); } int main() { // create thread std::thread th1 = std::thread([&]() { while(1) { m_mutex.lock(); cout << "thread1 working" << endl; Func(); m_mutex.unlock(); sleep(1); } }); th1.join(); while(1) { sleep(2); } return 0; }
運(yùn)行
[root@localhost ~]# ./testDeadLock thread1 working
發(fā)現(xiàn)程序卡住不動,無Func函數(shù)中的打印。
調(diào)試
[root@localhost deadLock]# ps -aux | grep testDeadLock root 88473 0.0 0.1 27200 1156 pts/1 Sl+ 14:13 0:00 ./testDeadLock root 88541 0.0 0.1 112832 996 pts/2 R+ 14:13 0:00 grep --color=auto testDeadLock [root@localhost deadLock]# gdb attach 88473 //... (gdb) info threads Id Target Id Frame 2 Thread 0x7f13e4603700 (LWP 88474) "testDeadLock" 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0 * 1 Thread 0x7f13e5a1d740 (LWP 88473) "testDeadLock" 0x00007f13e52ff017 in pthread_join () from /lib64/libpthread.so.0 (gdb) t 2 [Switching to thread 2 (Thread 0x7f13e4603700 (LWP 88474))] #0 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0 (gdb) bt #0 0x00007f13e530454d in __lll_lock_wait () from /lib64/libpthread.so.0 #1 0x00007f13e52ffe9b in _L_lock_883 () from /lib64/libpthread.so.0 #2 0x00007f13e52ffd68 in pthread_mutex_lock () from /lib64/libpthread.so.0 #3 0x0000000000402534 in __gthread_mutex_lock (__mutex=0x604120 <m_mutex>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/x86_64-redhat-linux/bits/gthr-default.h:748 #4 0x0000000000402584 in std::mutex::lock (this=0x604120 <m_mutex>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_mutex.h:103 #5 0x0000000000401f88 in Func () at source/test.cpp:12 #6 0x000000000040200a in <lambda()>::operator()(void) const (__closure=0x2439018) at source/test.cpp:28 #7 0x0000000000402242 in std::__invoke_impl<void, main()::<lambda()> >(std::__invoke_other, <unknown type in /home/testDeadLock, CU 0x0, DIE 0xada9>) ( __f=<unknown type in /home/testDeadLock, CU 0x0, DIE 0xada9>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/invoke.h:60 #8 0x000000000040209e in std::__invoke<main()::<lambda()> >(<unknown type in /mnt/hgfs/test/deadLock/debug.x64-linux-g8/testDeadLock, CU 0x0, DIE 0xb073>) ( __fn=<unknown type in /home/testDeadLock, CU 0x0, DIE 0xb073>) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/invoke.h:95 #9 0x0000000000402484 in std::thread::_Invoker<std::tuple<main()::<lambda()> > >::_M_invoke<0>(std::_Index_tuple<0>) (this=0x2439018) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:244 #10 0x000000000040245a in std::thread::_Invoker<std::tuple<main()::<lambda()> > >::operator()(void) (this=0x2439018) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:253 #11 0x000000000040243e in std::thread::_State_impl<std::thread::_Invoker<std::tuple<main()::<lambda()> > > >::_M_run(void) (this=0x2439010) at /opt/rh/devtoolset-8/root/usr/include/c++/8/thread:196 #12 0x00000000004028ff in execute_native_thread_routine () #13 0x00007f13e52fdea5 in start_thread () from /lib64/libpthread.so.0 #14 0x00007f13e4702b0d in clone () from /lib64/libc.so.6 (gdb) f 5 #5 0x0000000000401f88 in Func () at source/test.cpp:12 12 m_mutex.lock(); (gdb) p *(pthread_mutex_t*)$rdi $1 = {__data = {__lock = 2, __count = 0, __owner = 88474, __nusers = 1, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}}, __size = "\002\000\000\000\000\000\000\000\232Y\001\000\001", '\000' <repeats 26 times>, __align = 2} (gdb)
排查步驟
1) ps查看進(jìn)程id; 2) "gdb attach 進(jìn)程id"附加至該進(jìn)程; 3) "info threads"查看所有線程信息; 4) 查找有執(zhí)行鎖等待__lll_lock_wait ()的線程, 一般為死鎖線程, 切換至該線程, 如切換至線程2,則執(zhí)行"t 2"; 5) "bt" 查看當(dāng)前線程堆棧; 6) "f 幀數(shù)"切換至自己所寫代碼處; 7) "p *(pthread_mutex_t*)$rdi"打印寄存器信息, rdi為顯示寄存器; 8) 對7)的打印主要關(guān)注兩個地方,"__lock = 2"一般說明有死鎖, "__owner = 88474"代碼發(fā)生死鎖的線程, 與"info threads"的打印信息中 "(LWP 88474)"對應(yīng), 接下來直接分析88474指向的線程即可;
此排查方式適用于多個線程出現(xiàn)死鎖的情況。
遞歸鎖
遞歸鎖允許同一個線程在未釋放其擁有的鎖時反復(fù)對該鎖進(jìn)行加鎖操作。
示例
在c++11中,std::recursive_mutex 來支持遞歸鎖。
#include <iostream> #include <mutex> #include <thread> #include <unistd.h> using namespace std; std::recursive_mutex m_recursive_mutex; void Func() { std::lock_guard<std::recursive_mutex> mtx(m_recursive_mutex); cout << "Func" << endl; } int main() { // create thread1 std::thread th1 = std::thread([&]() { while(1) { std::lock_guard<std::recursive_mutex> mtx(m_recursive_mutex); cout << "thread1 working" << endl; Func(); sleep(1); } }); th1.join(); while(1) { sleep(2); } return 0; }
運(yùn)行
[root@localhost ~]# ./testDeadLock
thread1 working
Func
thread1 working
Func
thread1 working
Func
thread1 working
Func
程序可正常打印。
windows下遞歸鎖
特點
- windows下的互斥量和臨界區(qū)(關(guān)鍵段)默認(rèn)支持遞歸鎖;
- EnterCriticalSection可以被多次調(diào)用;
- EnterCriticalSection與LeaveCriticalSection調(diào)用次數(shù)必須對應(yīng);
- 臨界區(qū)函數(shù)如下:
// 初始化一個臨界區(qū)對象 void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection); // 刪除臨界區(qū)對象釋放由該對象使用的所有系統(tǒng)資源 void DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection); // 進(jìn)入臨界區(qū) void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); // 刪除臨界區(qū) void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
示例
#include <iostream> #include <thread> #include <Windows.h> using namespace std; CRITICAL_SECTION g_Critical; class CWinRecursiveLock { public: CWinRecursiveLock(CRITICAL_SECTION *pCritcal) { m_pCritical = pCritcal; EnterCriticalSection(m_pCritical); } ~CWinRecursiveLock() //析構(gòu)函數(shù) { LeaveCriticalSection(m_pCritical); } private: CRITICAL_SECTION *m_pCritical = nullptr; }; void Func() { CWinRecursiveLock wlock(&g_Critical); // 重復(fù)加鎖 cout << "Func" << endl; } int main() { // 初始化 InitializeCriticalSection(&g_Critical); std::thread th1 = std::thread([&]() { while(1) { CWinRecursiveLock wlock(&g_Critical); cout << "thread1 working" << endl; Func(); Sleep(1000); } }); th1.join(); system("pause"); return 0; }
經(jīng)測試,程序可正常運(yùn)行。
到此這篇關(guān)于c++ 遞歸鎖的使用的文章就介紹到這了,更多相關(guān)c++ 遞歸鎖的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
最短時間學(xué)會基于C++實現(xiàn)DFS深度優(yōu)先搜索
常見使用深度優(yōu)先搜索(DFS)以及廣度優(yōu)先搜索(BFS)這兩種搜索,今天我們就來講講什么是深度優(yōu)先搜索,感興趣的可以了解一下2021-08-08C語言與C++動態(tài)通訊錄超詳細(xì)實現(xiàn)流程
這篇文章主要為大家介紹了C語言與C++動態(tài)實現(xiàn)通訊錄,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-05-05