1. 程式人生 > >第一個多執行緒程式

第一個多執行緒程式

#include<windows.h>
#include <iostream>


DWORD WINAPI fun1Proc(
	LPVOID lpParameter  //thread data
);
DWORD WINAPI fun2Proc(
	LPVOID lpParameter  //thread data
);
int index = 0;
int tickets = 100;
HANDLE hMutex;
using namespace std;
int  main()
{
	HANDLE hThread1;
	HANDLE hThread2;
	hThread1 = CreateThread(NULL, 0, fun1Proc, NULL, 0, NULL);
	hThread2 = CreateThread(NULL, 0, fun2Proc, NULL, 0, NULL);
	CloseHandle(hThread1);
	CloseHandle(hThread2);
	hMutex = CreateMutex(NULL, FALSE, NULL);

	Sleep(4000);
	return 0;

}

//執行緒1的入口函式
DWORD WINAPI fun1Proc(
	LPVOID lpParameter  //thread data
)
{

	while (true)
	{
		WaitForSingleObject(hMutex, INFINITE);
		if (tickets>0)
		{
			cout << "thread1 sell ticket:" << tickets-- << endl;
		}
		else
		{
			break;
		}
		ReleaseMutex(hMutex);
	}
	return 0;
}


//執行緒2的入口函式
DWORD WINAPI fun2Proc(
	LPVOID lpParameter  //thread data
)
{

	while (true)
	{
		WaitForSingleObject(hMutex, INFINITE);
		if (tickets > 0)
		{
			cout << "thread2 sell ticket:" << tickets-- << endl;
		}
		else
		{
			break;
		}
		ReleaseMutex(hMutex);
	}
	return 0;
}


1

HANDLE hMutex;

hMutex = CreateMutex(NULL,FALSE,NULL);

是建立一個互斥物件控制代碼,用處是配合WaitForSingleObject(hMutex,INFINITE).當執行緒1和2執行到此句的時候都會等待,除非所等待的互斥物件:hMutex處於有訊號狀態,執行緒才會繼續執行下去。

當代碼操作完之後應呼叫ReleaseMutex函式釋放當前執行緒對互斥物件的所有權,這時,作業系統將該互斥物件的的執行緒ID置為0,然後將該互斥物件設為有訊號狀態(當互斥物件被使用時,置為無訊號狀態,哪裡使用WaitForSingleObject()此時的互斥物件hMutex的ID就置為當前程序中)。

2

若我們將主程式中hMutex = CreateMutex(NULL, FALSE, NULL),將FALSE改為TRUE此時,hMutex 擁有呼叫它執行緒的ID(本程式時mainID),這時執行程式發現兩個執行緒都不執行,因為main一直佔用hMute沒有釋放,hMute一直處於無訊號狀態,若在    hMutex = CreateMutex(NULL, TRUE, NULL);後加上ReleaseMutex(hMutex);則執行緒繼續執行。

對互斥物件來說,誰擁有誰釋放

3

int  main()
{
	HANDLE hThread1;
	HANDLE hThread2;
	hThread1 = CreateThread(NULL, 0, fun1Proc, NULL, 0, NULL);
	hThread2 = CreateThread(NULL, 0, fun2Proc, NULL, 0, NULL);
	CloseHandle(hThread1);
	CloseHandle(hThread2);
	hMutex = CreateMutex(NULL, TRUE, NULL);
	WaitForSingleObject(hMutex, INFINITE);
	ReleaseMutex(hMutex);
	
	//ReleaseMutex(hMutex);
	Sleep(4000);
	return 0;

}

當呼叫WaitForSingleObject函式請求互斥物件時,作業系統需要判斷當前請求互斥物件的執行緒ID是否與互斥物件當前擁有這的執行緒ID相等若相等,即使該互斥處於未通知狀態,呼叫執行緒仍然能有獲得其擁有權。

當主執行緒擁有該互斥物件時,該物件就處於未通知狀態,當主執行緒呼叫WaitForSingleObject函式請求該互斥物件的所有權時,因為請求的執行緒ID與和該互斥物件當前所有者的執行緒ID時相同時,所以仍然能夠請求到這個互斥物件,作業系統通過互斥物件內部的計數器來維護同一個執行緒請求到該互斥物件的的次數,於是計數器加1,這是計數器為2(當固定main函式ID時計算器+1,呼叫WaitForSingleObject時+1所以為2,計算器只有在為0時WaitForSingleObject才通過不等待)。所以需要呼叫兩次ReleaseMutex將計數器減為0,這是互斥物件hMutex有訊號,才能被執行緒接受。