臨界區爲非內核對象,優點速度快,效率高,缺點時間不好控制,有可能第二個線程永遠進不去 所以需要人爲的在執行完原子操作後sleep()把進入的線程的時間片讓出來
和mutex相似,也是進去一個就關門了 唯一不同的是兩個函數的使用時候存在死鎖的問題,不是操作系統控制,時間片不好控制
下面爲死鎖問題復現
下面剛進去a 睡眠20ms 20ms是人爲放大的間隙那邊b進去了等到釋放a才能進去 而這邊要等到b釋放了 才能進去釋放a 所以互相等 一直等
#include "iostream"
#include "windows.h"
using namespace std;
int g_iticket = 100;
unsigned long _stdcall bar(void*pramater);
unsigned long _stdcall bar1(void*pramater);
CRITICAL_SECTION csA; //臨界區 非內核讓出時間片的時候需要手動給一個sleep 工作在用戶區
CRITICAL_SECTION csB;
int main(void)
{
int inum1 = 1;
int inum2 = 2;
HANDLE thread1 = CreateThread(nullptr, 0, bar, &inum1, 0, nullptr);
HANDLE thread2 = CreateThread(nullptr, 0, bar1, &inum2, 0, nullptr);
InitializeCriticalSection(&csA);
InitializeCriticalSection(&csB);
if (thread1)
{
CloseHandle(thread1);
}
if (thread1)
{
CloseHandle(thread2);
}
Sleep(8000);
return 0;
}
//臨界區死鎖問題示例
unsigned long _stdcall bar(void*pramater)
{
int* inum = reinterpret_cast<int *>(pramater);
while (true)
{
EnterCriticalSection(&csA);
//Sleep(20); //人爲放大這個間隙 將時間片讓出來, 這個線程拿到了csa 後在這裏睡20ms ,下面的線程拿到了csb,上面sleep結束後等csb,下面結束後又在等csa 就這樣形成一直等的死鎖問題
EnterCriticalSection(&csB);
if (g_iticket > 0)
{
cout << "#" << *inum << ":" << g_iticket-- << endl;
LeaveCriticalSection(&csB);
LeaveCriticalSection(&csA);
Sleep(20); //
}
else
{
LeaveCriticalSection(&csB);
LeaveCriticalSection(&csA);
break;
}
}
return 0;
}
unsigned long _stdcall bar1(void*pramater)
{
int* inum = reinterpret_cast<int *>(pramater);
while (true)
{
EnterCriticalSection(&csB);
//Sleep(20);
EnterCriticalSection(&csA);
if (g_iticket > 0)
{
cout << "#" << *inum << ":" << g_iticket-- << endl;
LeaveCriticalSection(&csA);
LeaveCriticalSection(&csB);
Sleep(20);//
}
else
{
LeaveCriticalSection(&csA);
LeaveCriticalSection(&csB);
break;
}
}
return 0;
}