注意:mutex windows vista 以上系統用SRWLOCK 實現,winxp用的是參考 rtlocks.cpp
critical_section 調用InterlockedCompareExchangePointer 來實現的
Windows 7下 + vs2015 微軟最新c++11 std::mutex 內部實現剖析
一、 先說說微軟c++11 裏面實現的代碼,廢話不多說,上例子驗證猜想
Vs2015新建一個控制檯程序,代碼如下:
// mutex_d.cpp : 定義應用程序的入口點。
//此段代碼是死鎖程序,方便跳轉到內部實現!!!!
#include "stdafx.h"
#include "mutex_d.h"
#include<thread>
#include<mutex>
#include<iostream>
std::mutex test;
void t_fun()
{
test.lock();//重入導致死鎖
std::cout << "hello\n";
test.unlock();
}
int main(int argc, TCHAR* argv[])
{
test.lock();
std::thread th(t_fun);
th.join();
return 0;
}
/*
讀寫鎖 SRWLOCK 使用方法
SRWLOCK srw;
InitializeSRWLock(&srw);
//一旦初始化完成,就可以對寫入線程調用AcquireSRWLockExclusive()函數和ReleaseSRWLockExclusive()函數
AcquireSRWLockExclusive(&srw);
//...寫入數據,寫入東西的時候該線程獨佔,其他任何線程不可進入
ReleaseSRWLockExclusive(&srw);
//對於只讀線程可以調用AcquireSRWLockShared()函數和ReleaseSRWLockShared()函數, 如下
AcquireSRWLockShared(&srw);
//..讀取數據,如果這時沒有寫入數據則多個讀取線程可以進行
ReleaseSRWLockShared)&srw);
*/
運行程序會導致卡主不動,此時貼上堆棧:
ntdll.dll!_ZwWaitForKeyedEvent@16 ()
ntdll.dll!_RtlAcquireSRWLockExclusive@4 ()
msvcp140d.dll!__crtAcquireSRWLockExclusive(_RTL_SRWLOCK * pLock=0x00ff0388) 行 605
msvcp140d.dll!Concurrency::details::stl_critical_section_win7::lock() 行 166
msvcp140d.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx=0x00ff0380, const xtime * target=0x00000000) 行 100
msvcp140d.dll!_Mtx_lock(_Mtx_internal_imp_t * mtx=0x00ff0380) 行 186
mutex_d.exe!std::_Mtx_lockX(_Mtx_internal_imp_t * _Mtx=0x00ff0380) 行 70
mutex_d.exe!std::_Mutex_base::lock() 行 43
mutex_d.exe!t_fun() 行 16
mutex_d.exe!std::_Invoker_functor::_Call<void (__cdecl*)(void)>(void(*)() && _Obj=0x00fe1235) 行 1375
mutex_d.exe!std::invoke<void (__cdecl*)(void)>(void(*)() && _Obj=0x00fe1235) 行 1443
mutex_d.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Execute<0>(std::tuple<void (__cdecl*)(void)> & _Tup={...}, std::integer_sequence<unsigned int,0> __formal={...}) 行 240
mutex_d.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Run(std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > > * _Ln=0x0019f5d0) 行 247
mutex_d.exe!std::_LaunchPad<std::unique_ptr<std::tuple<void (__cdecl*)(void)>,std::default_delete<std::tuple<void (__cdecl*)(void)> > > >::_Go() 行 232
mutex_d.exe!std::_Pad::_Call_func(void * _Data=0x0019f5d0) 行 209
ucrtbased.dll!invoke_thread_procedure(unsigned int(__stdcall*)(void *) procedure=0x00fe11c2, void * const context=0x0019f5d0) 行 92
ucrtbased.dll!thread_start<unsigned int (__stdcall*)(void *)>(void * const parameter=0x005fdd50) 行 115
kernel32.dll!@BaseThreadInitThunk@12 ()
ntdll.dll!___RtlUserThreadStart@8 ()
ntdll.dll!__RtlUserThreadStart@8 ()
注意:如下三個函數其實是一樣的!!!!!
{
Kernel32.dll !AcquireSRWLockExclusive( PSRWLOCK SRWLock
ntdll.dll!_RtlAcquireSRWLockExclusive@4 ()
msvcp140d.dll!__crtAcquireSRWLockExclusive(_RTL_SRWLOCK * SRWLock)
}
結論 windows下 std:: mutex內部使用了讀寫鎖SRWLOCK 和 臨界區相似的功能!!
源碼位置:
Microsoft Visual Studio 14.0\VC\crt\src\stl\primitives.h
virtual void lock() override
{
__crtAcquireSRWLockExclusive(&m_srw_lock);
}