[Win32基础]线程同步概述

线程:需要同步对象在某些时候进行同步操作。

基本原理

线程同步机制是为各线程能够协同工作而设计的。同步是唯一保证共享数据持久的方法。

在同步过程中,两最重要的概念是同步对象(Mutex,Semaphore,Event,CriticalSection)和等待函数((WaitForSingleObject(),WaitForMultipleObjects())。同步对象是内存中的变量,你可以像访问一般的数据那样来访问他。

在线程同步过程中,需要先定义一个同步对象,同步对象一般具有两种状态:标志的(置位,signaled)和未标志的(未置位,nonsignaled)。线程根据是否已经完成操作将同步对象设置为标志的或未标志的。

而等待函数的功能是专门用于等待同步对象状态改变。一个线程调用等待函数后执行会暂停,直到同步对象的状态改变后,等待函数才会返回,线程才会继续执行。等待函数分为“单对象”等待函数和“多对象”等待函数。

小demo

/*
实例中UseEvents先创建一个事件对象,然后创建了线程,创建完成线程后,经过一段时间,向内存中复制数据,然后再置位。
被创建的线程EventFunction调用WaitForSingleObject函数等待事件置位,事件置位后,再读取内存,再复位事件(使未置位).
*/
#include <windows.h>
#include <stdio.h> 
/* 全局变量 */
HANDLE hEvent;					// 用于同步
BYTE lpSharedBuffer[16] = {0};	// 共享内存
/* 函数声明 */
void UseEvents(void);
DWORD WINAPI EventFunction(LPVOID lpParam);
 
int main()
{
	UseEvents();
	system("pause");
	return 0;
} 
void UseEvents(void) 
{ 
	hEvent = CreateEvent( 
		NULL,			// 默认安全属性
		TRUE,			// 手工重置
		FALSE,			// 初始为未置位的
		NULL			// 未命名
		);	
	if (hEvent == NULL) // 判断是否创建成功
	{ 
		printf("CreateEvent failed (%d)\n", GetLastError());
		return;
	} 
	HANDLE hThread;
	for(int a=0;a<10;a++)// 创建线程
	{
		hThread = CreateThread(NULL, 0, EventFunction, NULL,0, NULL); 
    	if (hThread == NULL) 
	    {
			printf("CreateThread failed (%d)\n", GetLastError());
		    return;
	    }	
	    Sleep(100); // 可以做一些其他处理
	}	
	CopyMemory(lpSharedBuffer,"Event",lstrlen("Event"));// 向共享内存中复制数据	
	SetEvent(hEvent);// 设置 Event 使ThreadFunction线程可以开始复制数据
} 
//线程函数,读共享内存
DWORD WINAPI EventFunction(LPVOID lpParam) 
{ 
	// 等待,直到事件被置位
	DWORD dwWaitResult = WaitForSingleObject( 
		hEvent,			// Event 句柄
		INFINITE);		// 无限等待
	if (dwWaitResult != WAIT_OBJECT_0) 
	{
		printf("Wait error: %d\n", GetLastError()); 
		return 0;
	}	
	printf("%s\n",lpSharedBuffer);// 读共享内存	
	if (! ResetEvent(hEvent) ) // 重置事件
	{ 
		printf("SetEvent failed (%d)\n", GetLastError());
		return 0;
	}
	return 1;
}

 

线程同步的过程

同步对象与等待函数相互配合以实现线程同步。比如,线程A在进行某种操作前需要线程B为其准备好数据,那忙这种时候就需要线程同步。线程A会等待线程B的执行,直到需要的数据准备好。那么使用同步对象和等待函数,其过程基本如下:

  • 在需要进行线程同步的进程中定义某种同步对象,同步对象必需是全局的,以保证需要同步的线程AB都可以访问到同步对象。
  • 开始时,线程AB相互独立地执行。
  • 线程B在准备好线程A需要使用到的数据前,将同步对象置位"未标记的",线程B在准备好线程A需要使用的数据后,改变同步对象的状态,置为"标记的"
  • 线程A运行,直到需要线程B为其准备的数据时,调用等待函数。如果同步对象不是"标记的",则一直等待到同步对象的状态改变到"标记的"为止。同步对象被B设置为"标记的"(表示线程B已经完成数据准备工作),等待函数才会返回,线程A继续执行。
  • 以此类推,循环往复。 
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页