[基础]同步对象

同步对象

/************************************************************************/
/*                                      同步对象(Mutex)
互斥对象具有的机制:如果互斥对象没有被任何线程拥有,那么它是"标记的",如果被一个线程所拥有,那么它是"未标志的";任何一个线程获得后,互斥对象就是"未标志的",
                               其他线程不可以再拥有这个互斥对象。同一时刻,一个互斥对象最多只能被一个线程拥有,从而实现"互斥"。
概览
       同一时刻只有一个线程可以拥有Mutex对象
	   全局名称的Mutex可以跨进程使用
	   在没有线程拥有它时处于通知(置位)状态
	   被线程拥有的时候处于非通知(非置位)状态
函数
       创建一个Mutex同步对象
	   HANDLE CreateMutex( 
	   __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,//不支持,设置为NULL
	   __in BOOL bInitialOwner,        //是否为创建该Mutex的线程所拥有
	   __in_opt LPCSTR lpName );     //可选,该Mutex的名字
	   释放对Mutex的占用
	   BOOL ReleaseMutex( //一个线程释放了互斥对象后,如果其他线程在等待互斥对象置位,则等待的线程可以得到该互斥对象,等待函数返回,互斥对象被新的线程所拥有
	   __in HANDLE hMutex   //Mutex的句柄
	   );
*/
/************************************************************************/

/************************************************************************/
/*                                     同步对象(Semaphore)
信号量维护了一个计数器,计数器的值可以在0到指定的最大值之间。
当一个线程完成了对信号量的等待后,信号量计数器值减少;当一个线程释放信号量是,信号量计数器值增加。
当计数器值达到零后,信号量是"未标志的",当计数器值大于零时,信号量是“标志的”。
当计数器值降为到零时,任何线程都无法等待信号量变为“标志的”,因此信号量对限制可访问共享数据的线程数量很有用处。
使用信号量可以达到限制访问共享数据的线程数量的功能。
概览
       限制占有共享资源的数量(如果一个Semaphore带有计数n,这表示同时最多可以有n个线程占有该Semaphore)
	   全局名称的Semaphore可以跨进程使用
	   引用计数大于0时处于通知状态
	   引用计数小于等于0时处于非通知状态
函数
       创建一个Semaphore对象
	   HANDLE WINAPI CreateSemaphore(
	   __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //不支持,设为NULL
	   __in     LONG lInitialCount,         //初始计数值
	   __in     LONG lMaximumCount,  //最大支持的线程数,最大计数值
	   __in_opt LPCWSTR lpName )       //可选,semaphore的名字
	   释放Semaphore
	   BOOL ReleaseSemaphore( 
	   __in HANDLE hSemaphore,                //要释放的Semaphore句柄
	   __in LONG lReleaseCount,                  //释放的引用个数,可以一次释放多个计数
	   __out_opt LPLONG lpPreviousCount ) //返回释放前的semaphore计数
*/
/************************************************************************/

/************************************************************************/
/*                                      同步对象(Event)
概览
       全局名称的Event可以跨进程使用
	   事件发生时处于通知状态
	   事件未发生时处于非通知状态
函数
       创建同步对象Event
	   HANDLE CreateEvent(
	   __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,  //不可用,设为NULL
	   __in     BOOL bManualReset,               //是否需要人工重置,所谓重置是指将已标记的事件对象再重新设置为未标志。如果为TRUE,
	                                                             //则需ResetEvent()来重置,如果为FALSE,那么等待函数在等待到事件置位后,自动将事件重置。
	   __in     BOOL bInitialState,                   //初始状态,TRUE为通知状态
	   __in_opt LPCWSTR lpName                  //可选,Event的名字
	   )
	   把Event同步对象设置为通知状态/未通知状态
	   BOOL SetEvent( __in HANDLE hEvent )   //Event的句柄
	   BOOL ResetEvent( __in HANDLE hEvent )//Event的句柄,将事件重置为"未通知"状态。如果事件时手工重置的,那么需要使用此函数爱重置事件。
*/
/************************************************************************/

/************************************************************************/
/*                                             同步(CriticalSection)
概览
       允许多个线程共享访问同一块数据
	   使用互斥访问保护数据
	   其他线程会block直到占用者放弃临界区
	   每个CriticalSection都是OS提供的一个数据结构,只能在同一个进程内部使用,比Mutex要高效
函数
       InitializeCriticalSection( __out LPCRITICAL_SECTION lpCriticalSection );   //分配CriticalSection结构
	   EnterCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );    //在占有CriticalSection的线程调用LeaveCriticalSection之前会阻塞
	   TryEnterCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );//EnterCriticalSection的非阻塞版
	   LeaveCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );    //释放CriticalSection的所有权
	   DeleteCriticalSection( __inout LPCRITICAL_SECTION lpCriticalSection );   //释放InitializeCriticalSection分配的资源
*/
/************************************************************************/

Mutex实例

//实例  使用Mutex对象对共享的全局变量iData进行访问
#include <windows.h>
#include <stdio.h>
HANDLE hMutex;
int iData=0;
DWORD WINAPI ThreadProc1(LPVOID lParam)
{
	WaitForSingleObject(hMutex,INFINITE);     //获取Mutex对象
	for (int i=0;i<(int)lParam;i++)             
	{
		iData++;                                               //访问共享资源
		printf("iData++ %d\n",iData);
	}
	ReleaseMutex(hMutex);                             //释放同步对象
	return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lParam)
{
	WaitForSingleObject(hMutex,INFINITE);     //获取Mutex对象
	for (int i=0;i<(int)lParam;i++)
	{
		iData--;                                                 //访问共享资源
		printf("iData-- %d\n",iData);
	}
	ReleaseMutex(hMutex);                             //释放同步对象
	return 0;
}
void Init()
{
	hMutex=CreateMutex(NULL,FALSE,NULL);
	CreateThread(NULL,0,ThreadProc1,(LPVOID)4,0,NULL);
	CreateThread(NULL,NULL,ThreadProc2,(LPVOID)5,NULL,NULL);
}
int main()
{
	Init();
	system("pause");
	return 0;
}

Event实例

//实例  使用Event对象对共享的全局变量进行访问
#include <windows.h>
#include <stdio.h>
HANDLE hEvent;
int iData=0;
DWORD WINAPI ThreadProc1(LPVOID lParam)
{
	WaitForSingleObject(hEvent,INFINITE);   //等待事件发生
	for (int i=0;i<(int)lParam;i++)
	{
		iData++;                                            //访问共享资源
		printf("iData++ %d\n",iData);
	}
	SetEvent(hEvent);                                    //让事件再次发生
	return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lParam)
{
	WaitForSingleObject(hEvent,INFINITE);   //等待事件发生
	for (int i=0;i<(int)lParam;i++)
	{
		iData--;                                              //访问共享资源
		printf("iData-- %d\n",iData);
	}
	SetEvent(hEvent);                                   //让事件再次发生
	return 0;
}
VOID Init()
{
	hEvent=CreateEvent(NULL,FALSE,TRUE,NULL);
	CreateThread(NULL,NULL,ThreadProc1,(LPVOID)4,NULL,NULL);
	CreateThread(NULL,NULL,ThreadProc2,(LPVOID)5,NULL,NULL);
}
int main()
{
	Init(); 
	system("pause");
	return 0;
}

CriticalSection实例

//实例 使用CriticalSection对象对共享的全局变量进行访问
#include <windows.h>
#include <stdio.h>
CRITICAL_SECTION cs;
int iData=0;

DWORD WINAPI ThreadProc1(LPVOID lParam)
{
	EnterCriticalSection(&cs);           //进入临界区
	for (int i=0;i<(int)lParam;i++)
	{
		iData++;                                //访问共享数据
		printf("iData++ %d\n",iData);
	}
	LeaveCriticalSection(&cs);           //离开临界区
	return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lParam)
{
	EnterCriticalSection(&cs);           //进入临界区
	for (int i=0;i<(int)lParam;i++)
	{
		iData--;                                //访问共享数据
		printf("iData-- %d\n",iData);
	}
	LeaveCriticalSection(&cs);           //离开临界区
	return 0;
}
void Init()
{
	InitializeCriticalSection(&cs);
	CreateThread(NULL,NULL,ThreadProc1,(LPVOID)4,NULL,NULL);
	CreateThread(NULL,NULL,ThreadProc2,(LPVOID)5,NULL,NULL);
}
int main()
{
	Init();
	system("pause");
	return 0;
}

上面3个实例的结果都是:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值