更新时间:2015-11-09 14:21:32浏览次数:1+次
#include <windows.h> //包含头文件
#include <stdio.h>
DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
HANDLE hmutex;
int a=0; //定义全局变量a
int main()
{
hmutex=::CreateMutex(NULL,FALSE,NULL); //创建互斥对象并返回其句柄
HANDLE h1,h2; //定义线程句柄
h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL); //创建线程1
printf("线程1开始运行!\r\n");
h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL); //创建线程2
printf("线程2开始运行!\r\n");
::CloseHandle(h1); //关闭线程句柄对象
::CloseHandle(h2);
::Sleep(10000); //程序睡眠10秒
return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter) //线程函数1
{
while(1)
{
::WaitForSingleObject(hmutex,INFINITE); //请求互斥对象
if(a<10000)
{
a+=1; //变量自加
::Sleep(1000); //线程睡眠1秒
printf("线程1:%d\r\n",a);
::ReleaseMutex(hmutex); //释放互斥对象句柄
}
else
{
::ReleaseMutex(hmutex); //释放互斥对象句柄
break;
}
}
return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter) //线程函数2
{
while(1)
{
::WaitForSingleObject(hmutex,INFINITE); //请求互斥对象
if(a<10000)
{
a+=1;
::Sleep(1000);
printf("线程2:%d\r\n",a); //输出变量
::ReleaseMutex(hmutex); //释放互斥对象句柄
}
else
{
::ReleaseMutex(hmutex); //释放互斥对象句柄
break; //跳出循环
}
}
return 0; //线程正常退出
}
这是利用互斥器来实现线程同步的,可是你确定你懂它的运行机制吗?那我们来说说吧。
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, 安全属性结构指针,可为NULL,表示默认安全性
BOOL bInitialOwner, //拥有互斥对象的线程(一般是主线程)是否占有该互斥量,TRUE:占有,FALSE:不占有
LPCTSTR lpName //设置互斥对象的名字
);
线程的执行是异步的,但是这里的同步机制-互斥器能让线程执行同步。在windows内核中,内核层包含了基本的操作系统原语和功能,控制线程和进程,线程调度,中断,同步对象等。内核层管理来你工作类型的对象,分发器对象和控制对象。分发器对象包含了各种同步功能,分发器对象包括事件,信号量,互斥器等,内核控制线程的切换(windows操作系统是实现各种线程的操作来完成任务的),内核根据调度规则来放弃或选择线程的执行状态,内核层中的分发器对象管理这些。那么在一个特定的一个线程分配到的运行时间就得受内核对象的控制,如果该内核对象没有满足它的激发条件,则该线程只得暂停,这就保证了线程的同步。
线程其实就是按照这种情节来执行的:
1,我们有一个mutex,此时没有任何线程拥有它,也就是说他处于激发状态。
2,某个线程调用waitforsingleobject()。
3,win32将这个互斥器的拥有权交给该线程。
4,Mutex立刻被设定为非激发状态。使得任何其他等待状态下的其他线程没有办法拥有其所有权。
5,获得该 mu tex 之线程调用 ReleaseMutex() ,将 mu tex 释放掉。于是循
环回到第一场景,周而复始。
而最后则是通过引用计数的计数值来删除核心对象-互斥器。随着程序代码的执行,CloseHandle(),或是ReleaseMutex,或是当线程结束时,mutex的引用计数就会减一。直到引用计数为0,最后才是销毁了它。
这就是大概的互斥器对象运行机制
相关资讯