多線程實現線程同步~~臨界區對象

原文地址:多線程實現線程同步~~臨界區對象 - 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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章