原文地址:多線程實現線程同步——互次對象 - CSDN博客 http://blog.csdn.net/qq_25425023/article/details/45287071
多線程實現線程同步——互次對象
互次對象實現線程同步。
1.使用API函數操作互次對象。
函數CreateMutex用於創建並返回互次對象。
函數原型:
HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD
BOOL bInitialOwner, // initial owner
LPCTSTR lpName // object name);
參數lpMutexAttributes指定新創建互次對象的安全屬性。如果該參數爲NULL,表示互次對象擁有默認安全屬性。
參數bInitialOwner表示該互次對象的擁有者。如果爲true,則表示創建該互次對象的線程擁有其所有權。如果爲false,表示創建的互次對象的線程不能擁有該互次對象的所有權。
參數lpName表示互次對象的名稱。若該參數爲NULL,則表示程序創建的是匿名對象,如果爲該參數指定值,則可以通過調用函數OpenMutex打開一個命名的互次對象。
調用函數ReleaseMutex釋放該對象的所有權,也就是讓該互次對象處於有信號狀態。
函數原型:
BOOL ReleaseMutex( HANDLE hMutex // handle to mutex);
下面是C語言實現的代碼:
#include <stdio.h>
#include <windows.h>
DWORD WINAPI myfun1(LPVOID lpParameter); //聲明線程函數
DWORD WINAPI myfun2(LPVOID lpParameter);
HANDLE hmutex;
int a = 0;
int main()
{
hmutex = ::CreateMutex(NULL, FALSE, NULL);
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(10000);
return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter)
{
while(1)
{
::WaitForSingleObject(hmutex, INFINITE); //請求互次對象
if(a < 1000)
{
a += 1;
::Sleep(1000);
printf("線程1正在計數%d\r\n", a);
::ReleaseMutex(hmutex); //釋放互次對象句柄
}
else
{
::ReleaseMutex(hmutex);
break;
}
}
return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter)
{
while(1)
{
::WaitForSingleObject(hmutex, INFINITE);
if(a < 1000)
{
a += 1;
::Sleep(1000);
printf("線程2正在計數%d\r\n", a);
::ReleaseMutex(hmutex);
}
else
{
::ReleaseMutex(hmutex);
break;
}
}
return 0;
}
2.使用CMutex類
創建CMutex類對象是通過其構造函數實現的。
構造函數原型:
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
代碼:
#include <stdio.h>
#include <afxmt.h>
DWORD WINAPI myfun1(LPVOID lpParameter); //聲明線程函數
DWORD WINAPI myfun2(LPVOID lpParameter);
CMutex hmutex(NULL, FALSE, NULL);
int a = 0;
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(10000);
return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter)
{
while(1)
{
hmutex.Lock(INFINITE); //鎖定互次對象
if(a < 1000)
{
a += 1;
::Sleep(1000);
printf("線程1: %d\r\n", a);
hmutex.Unlock(); //解鎖互次對象
}
else
{
hmutex.Unlock();
break;
}
}
return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter)
{
while(1)
{
hmutex.Lock(INFINITE);
if(a < 1000)
{
a += 1;
::Sleep(1000);
printf("線程2: %d\r\n", a);
hmutex.Unlock();
}
else
{
hmutex.Unlock();
break;
}
}
return 0;
}
結果: