在windows,线程同步的方式比较多,这篇只是简单的介绍使用内核对象互斥量进行线程同步,互斥量Mutex为内核对象,使用方式原理和临界区CriticalSection差不多,临界区是基于用户空间进行线程同步的,只能进行同一个进程中线程的同步,不能跨进程,因为不是基于内核态的.下边是一个简单那的线程同步的例子.
编程步骤:
1,创建互斥量,2等候互斥量,3,释放互斥量,4,关闭互斥量,从等候互斥量到释放互斥量之间的代码块是原子执行的,一个线程等候到互斥量之后(A),在释放之前(B),其他线程是无法访问A-B之间的代码块的.这一点和临界区是一样的.在存在资源共享时,多线程同时处理共享数据,为了保证数据的完整性和安全性,可以采用这种方式进行同步.
主要用到的函数.
HANDLE CreateMutex( //函数功能:创建互斥量 LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD 互斥量安全属性,一般内核对象都会有此数据结构 BOOL bInitialOwner, // initial owner 初始化的拥有者,谁初始拥有其执行权 LPCTSTR lpName // object name 内核对象名字,跨进程通信时使用. );
DWORD WaitForSingleObject( //等候互斥量, HANDLE hHandle, // handle to object //互斥量句柄 DWORD dwMilliseconds // time-out interval 等候的超时时间 );
BOOL ReleaseMutex( //释放互斥量,使其让其他线程拥有 HANDLE hMutex // handle to mutex 句柄 );
// Mutex.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
HANDLE g_hMutex=NULL;
//线程函数
DWORD WINAPI ThreadFun1(LPVOID);
DWORD WINAPI ThreadFun2(LPVOID);
DWORD WINAPI ThreadFun3(LPVOID);
int _tmain(int argc, _TCHAR* argv[])
{
//创建互斥对象
g_hMutex=CreateMutex(NULL,FALSE,NULL); //如果此处第二个参数为true,那就是主线程为互斥量的拥有者,这样,主线程不释放,其他线程只能等候.为false的话,谁先等候,谁先获取到,这个有操作系统决定.
//创建线程
DWORD threadID=0;
HANDLE hThread[3]={0};
hThread[0]=CreateThread(NULL,0,ThreadFun1,NULL,0,&threadID);
hThread[1]=CreateThread(NULL,0,ThreadFun2,NULL,0,&threadID);
hThread[2]=CreateThread(NULL,0,ThreadFun3,NULL,0,&threadID);
WaitForMultipleObjects(3,hThread,TRUE,INFINITE);
CloseHandle(g_hMutex);
return 0;
}
VOID WINAPI Show(CHAR* str)
{
//如果将等候和释放注释掉,则三个线程异步运行,各自独立运行,则每秒各自执行一次.
//等待互斥
WaitForSingleObject(g_hMutex,INFINITE);
printf("------------%s----------------\n",str);
Sleep(1000);
//释放互斥
ReleaseMutex(g_hMutex);
}
DWORD WINAPI ThreadFun2( LPVOID param )
{
while(1)
{
Show("线程2");
}
return 0;
}
DWORD WINAPI ThreadFun1( LPVOID param )
{
while(1)
{
Show("线程1");
}
return 0;
}
DWORD WINAPI ThreadFun3( LPVOID param )
{
while(1)
{
Show("线程3");
}
return 0;
}