原文地址:多線程實現線程同步~~臨界區對象 - CSDN博客
http://blog.csdn.net/qq_25425023/article/details/45253237
多線程實現線程同步~~臨界區對象
線程同步是指同一進程中的多個線程互相協調工作達到一致。有時在編寫程序時,會使多個代碼段同時讀取或修改相同地址空間中的共享數據。此時,在操作系統中,可能會出現一個代碼段在讀取數據,另一個代碼段在修改數據,這樣會導致程序發生讀寫錯誤!而解決這樣的問題,需要使用線程同步技術。
臨界區對象
臨界區對象,是指當使用某個線程訪問共享資源時,必須使代碼段獨享該資源,不允許其他線程返問該資源。
這裏將分享兩種方法,一種是API函數,另一種是MFC類。
API函數:
需要調用函數InitializeCriticalSection對臨界區對象進行初始化。
函數原型:
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // critical section);
參數是一個指向結構體CRITICAL_SECTION的指針變量。
需要調用函數EnterCriticalSection進入臨界區。
函數原型:
VOID EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // critical section);
參數同上。
需要調用函數LeaveCriticalSection離開臨界區。
函數原型:
VOID LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // critical section);
參數同上。
如果調用線程釋放臨界區的所以權之後,應該使用函數DeleteCriticalSection將臨界區從內存中刪除。
函數原型:
VOID DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // critical section);
參數同上。
下面是C語言實現:
#include <stdio.h>
#include <windows.h>
DWORD WINAPI myfun1(LPVOID lpParameter); //聲明線程函數
DWORD WINAPI myfun2(LPVOID lpParameter);
static int a1 = 0;
CRITICAL_SECTION Section1;
int main()
{
HANDLE h1, h2;
InitializeCriticalSection(&Section1); //初始化臨界區對象
h1 = ::CreateThread(NULL, 0, myfun1, NULL, 0, NULL); //創建線程
printf("線程1開始運行!\r\n");
h2 = ::CreateThread(NULL, 0, myfun2, NULL, 0, NULL);
printf("線程2開始運行!\r\n");
::CloseHandle(h1); //關閉線程句柄對象
::CloseHandle(h2);
::Sleep(10000);
printf("按q正常退出!\r\n");
if(getchar() == 'q')
{
DeleteCriticalSection(&Section1);
}
else
{
return 0;
}
return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter)
{
while(1)
{
EnterCriticalSection(&Section1); //進入臨界區
::Sleep(1000);
a1++;
if(a1 < 1000)
{
// ::Sleep(1000);
printf("線程1正在計數%d\r\n", a1);
LeaveCriticalSection(&Section1); //離開臨界區
::Sleep(1000);
}
else
{
LeaveCriticalSection(&Section1);
break;
}
}
return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter)
{
while(1)
{
EnterCriticalSection(&Section1);
::Sleep(1000);
a1++;
if(a1 < 1000)
{
// ::Sleep(1000);
printf("線程2正在計數%d\r\n", a1);
LeaveCriticalSection(&Section1);
::Sleep(1000);
}
else
{
LeaveCriticalSection(&Section1);
break;
}
}
return 0;
}
結果:
下面的是MFC類:
MFC類用Lock鎖定臨界區,unLock對臨界區進行解鎖。
MFC類,需要添加頭文件:#include <afxmt.h>
#include <stdio.h>
//#include <windows.h>
#include <afxmt.h>
DWORD WINAPI myfun1(LPVOID lpParameter); //聲明線程函數
DWORD WINAPI myfun2(LPVOID lpParameter);
int a1 = 0;
CCriticalSection m_sec;
int main()
{
HANDLE h1, h2;
h1 = ::CreateThread(NULL, 0, myfun1, NULL, 0, NULL); //創建線程
printf("線程1開始運行!\r\n");
h2 = ::CreateThread(NULL, 0, myfun2, NULL, 0, NULL);
printf("線程2開始運行!\r\n");
::CloseHandle(h1); //關閉線程句柄對象
::CloseHandle(h2);
::Sleep(5000);
return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter)
{
m_sec.Lock();
a1++;
::Sleep(1000);
printf("線程1正在計數%d\r\n", a1);
m_sec.Unlock();
return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter)
{
m_sec.Lock();
a1++;
::Sleep(1000);
printf("線程2正在計數%d\r\n", a1);
m_sec.Unlock();
return 0;
}
結果:
對於多線程,也只是初步的瞭解,慢慢深入吧!!~~
InitializeCriticalSection。