【讀書筆記】Windows CE嵌入式系統_【4】_線程同步

開篇

1、WinCE提供了Mutex,Event 和 Semaphore 三種內核機制來實現線程之間的同步。

     WinCE提供了兩種用戶態下的同步方法:Critical Section 和互鎖函數(Interlocked Functions)-----------不能跨進程,運行效率高

2、同步對象有兩種狀態:

  • 通知(Signaled)                   
  • 未通知(Non-signaled)     -------表示同步對象被佔用

3、等待同步對象函數



WaitForSingleObject()用來等待單個同步對象,WaitForMultipleObjects()用來等待多個同步對象。

參數dwMilliseconds,用來指定等待時間,單位百毫秒。如果設置成INFINITE,則一直等待同步對象變爲通知狀態。如果設置爲其它值,則當等待時間耗盡返回,即使同步對象依然處於未通知狀態。

Mutex--互斥(內核態)

如果某些共享資源同時只能被一個線程訪問,則優選Mutex。


孫鑫教學視頻第15課中的代碼
#include <windows.h>
#include <iostream.h>
//聲明線程入口函數原型
DWORD WINAPI Fun1Proc(  LPVOID lpParameter );
DWORD WINAPI Fun2Proc(  LPVOID lpParameter );
int tickets = 100; //要銷售的票數還剩下100張
//這100張票由Fun1Proc與Fun2Proc兩個線程負責銷售

HANDLE hMutex;//互斥對象句柄

void main()
{	
	HANDLE  hThread1,hThread2;
	hThread1 = CreateThread(
		NULL,	//使用缺省的安全性
		0,		//指定初始提交棧的大小
		Fun1Proc,//指定線程入口函數地址
		NULL,	//傳遞給線程的參數
		0,		//附加標記,0表示線程創建後立即運行
		NULL);	//線程ID,在Win98/95中不能設置爲NULL
	CloseHandle(hThread1);
	hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
	CloseHandle(hThread2);
//	cout<<"main thread is running"<<endl;
//	hMutex = CreateMutex(NULL, FALSE,NULL);
		//創建一個匿名的互斥對象
	hMutex = CreateMutex(NULL, TRUE,"MuName");
		//創建一個命名的互斥對象
	if(hMutex)
	{//判斷是不是第一次創建的互斥對象
		if(ERROR_ALREADY_EXISTS == GetLastError())
		{//如果爲真,說明互斥對象已經創建
			cout<<"已經有一個實例在運行了,只能有一個實例運行同時運行。"<<endl;
			return;
		}
	}
	WaitForSingleObject(hMutex,INFINITE);
		//因爲請求的互斥對象線程ID與擁有互斥對象線程ID相同,
		//可以再次請求成功,計數器加1
	ReleaseMutex(hMutex);  //第一次釋放,計數器減1,但仍有信號
	ReleaseMutex(hMutex);  //再一次釋放,計數器爲零

	while(tickets>0)	{ Sleep(4000);}
}//endof main()
/*------------實現線程入口函數Fun1Proc---------------*/
DWORD WINAPI Fun1Proc(  LPVOID lpParameter )
{	
	while(TRUE)
	{
		WaitForSingleObject(hMutex,INFINITE);
			//請求互斥對象
		if(tickets>0)
		{Sleep(1);
			cout<<"thread 1 sell ticket: ";
			cout<<tickets--<<endl;
		}
		else  
			break;
		ReleaseMutex(hMutex);

	}
	return 0;
}	///endof Fun1Proc()

/*-----------實現線程入口函數Fun2Proc--------------*/
DWORD WINAPI Fun2Proc(  LPVOID lpParameter )
{	
	while(TRUE)
	{
		WaitForSingleObject(hMutex,INFINITE);
		if(tickets>0)
		{Sleep(1);
			cout<<"thread 2 sell ticket: ";
			cout<<tickets--<<endl;
		}
		else
			break;
		ReleaseMutex(hMutex);
	}
	return 0;
}	///endof Fun1Proc()

Semaphore----信標或信號燈,→→帶有引用計數的Mutex (內核態)

如果共享資源同時只能被固定數量的線程使用,那麼優選Semaphore。



佔用時,lInitialCount,增加1;施放時,lInitialCount,減少一。

Event-----事件(內核態)




孫鑫教學視頻16課中的源碼
#include <windows.h>
#include <iostream.h>

int ticket=100;
HANDLE g_hEvent;//保存事件對象句柄

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

void main()
{
	HANDLE thread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
	HANDLE thread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
	
	CloseHandle(thread1);
	CloseHandle(thread2);
	//創建事件對象,可用命名事件對象來控制只運行一個實例
	g_hEvent=CreateEvent(NULL,
		FALSE,	//TRUE人工重置,FALSE 自動重置
		FALSE,	//初始化狀態,TURE信號狀態,FALSE非信號狀態
		"tickets");	//事件對象命名,NULL表示匿名
	if(g_hEvent)
	{
		if(ERROR_ALREADY_EXISTS == GetLastError())
		{
			cout<<"Only one instance can run!"<<endl;
			return;
		}
	}
	SetEvent(g_hEvent);//將事件設置爲有信號狀態
	Sleep(4000);
	CloseHandle(g_hEvent);
	
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
	WaitForSingleObject(g_hEvent,INFINITE);
	
	while(ticket)
	{
		cout<<"thread1 sells : "<<ticket--<<endl;
		Sleep(1);
		SetEvent(g_hEvent);
	}
	
	return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
	WaitForSingleObject(g_hEvent,INFINITE);
	while(ticket)
	{
		cout<<"thread2 sells : "<<ticket--<<endl;
		Sleep(1);
    SetEvent(g_hEvent);
	}
	
	return 0;
}

Critical Section ---------臨界區(用戶態)

Critical Section 是應用程序分配的一個數據結構。用來把一段代碼標記爲臨界區。

在使用Critical Section時,一般爲每一個共享資源分配一個Critical Section變量。應該把儘可能少的代碼放在Critical Section中。

互鎖函數




示例代碼


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