创建互斥对象同步线程
2010-01-13 10:40
387 查看
互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID和一个计数器。其中ID用于表示系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。
#include<windows.h>
#include<iostream.h>
DWORD WINAPI fun1proc(LPVOID lpParameter);
DWORD WINAPI fun2proc(LPVOID lpParameter);
int index=0;
int tickets=100;
HANDLE hMutex;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,fun1proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,fun2proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
//第一个参数NULL让互斥对象适应默认的安全性,FALSE创建互斥对象的线程不对
//互斥对象具有所有权,也就是互斥对象无所有权。
//第三个参数创建一个匿名的互斥对象
hMutex=CreateMutex(NULL,FALSE,NULL); //创建互斥对象
Sleep(4000);
}
DWORD WINAPI fun1proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket"<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
DWORD WINAPI fun2proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket"<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
代码执行顺序
在创建互斥对象时,第二个参数传递的是FALSE值,这表明当前没有线程拥有这个互斥对象,于是操作系统会将该互斥对象设置为有信号状态。当第一个线程开始运行时,进入while循环后,调用WaitForSingleObject函数,因为这个互斥对象处于有信号状态,所以两个线程总有个一个会请求到这个互斥对象。
比如线程1请求到了互斥对象,操作系统会将该互斥对象的线程ID设置为线程1的ID,接着操作系统会将这个互斥对象设置为未通知状态。线程1继续往下运行,调用Sleep函数,于是暂停执行。操作系统就会选择线程2开始执行,进入while循环后,调用WaitForSingleOBject函数,但这时该互斥对象已经被线程1所用有,处于未通知状态,线程2没有获得互斥对象的所有权,因此WaitForSingle函数就会处于等待状态,从而导致线程2处于暂停状态。当线程1的睡眠时间到以后,线程1将会继续执行,即销售一张火车票。
这时线程1执行到调用ReleaseMutex函数释放互斥对象的所有权,也就是让互斥象处于通知状态。互斥对象的一个循环走完。两个线程又处于同一起点开始请求互斥对象。
#include<windows.h>
#include<iostream.h>
DWORD WINAPI fun1proc(LPVOID lpParameter);
DWORD WINAPI fun2proc(LPVOID lpParameter);
int index=0;
int tickets=100;
HANDLE hMutex;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,fun1proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,fun2proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
//第一个参数NULL让互斥对象适应默认的安全性,FALSE创建互斥对象的线程不对
//互斥对象具有所有权,也就是互斥对象无所有权。
//第三个参数创建一个匿名的互斥对象
hMutex=CreateMutex(NULL,FALSE,NULL); //创建互斥对象
Sleep(4000);
}
DWORD WINAPI fun1proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket"<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
DWORD WINAPI fun2proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket"<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
代码执行顺序
在创建互斥对象时,第二个参数传递的是FALSE值,这表明当前没有线程拥有这个互斥对象,于是操作系统会将该互斥对象设置为有信号状态。当第一个线程开始运行时,进入while循环后,调用WaitForSingleObject函数,因为这个互斥对象处于有信号状态,所以两个线程总有个一个会请求到这个互斥对象。
比如线程1请求到了互斥对象,操作系统会将该互斥对象的线程ID设置为线程1的ID,接着操作系统会将这个互斥对象设置为未通知状态。线程1继续往下运行,调用Sleep函数,于是暂停执行。操作系统就会选择线程2开始执行,进入while循环后,调用WaitForSingleOBject函数,但这时该互斥对象已经被线程1所用有,处于未通知状态,线程2没有获得互斥对象的所有权,因此WaitForSingle函数就会处于等待状态,从而导致线程2处于暂停状态。当线程1的睡眠时间到以后,线程1将会继续执行,即销售一张火车票。
这时线程1执行到调用ReleaseMutex函数释放互斥对象的所有权,也就是让互斥象处于通知状态。互斥对象的一个循环走完。两个线程又处于同一起点开始请求互斥对象。
相关文章推荐
- (C#) Lock - 将对象上锁,互斥多个线程,使同步。
- 线程的同步互斥之事件对象(Event)
- Windows编程-- 线程和内核对象的同步 - 互斥对象内核对象
- 【Python】线程的创建、执行、互斥、同步、销毁
- 事件对象 互斥对象对 线程的同步
- 互斥对象_打印字符串_2线程_同步
- 【C++】Windows线程的创建、执行、互斥、同步、销毁
- linux 线程创建 同步与互斥
- MFC_互斥对象_打印字符串_2线程_同步
- 线程的创建、等待、终止、分离、同步和互斥
- 【IO进程】守护进程,线程创建、同步与互斥
- 同时创建多个线程,它们都访问一个对象中的同步方法,怎么确保第一个线程最先拿到对象锁,否则,怎么保证多个线程之间的有序通信
- UNIX网络编程卷1 服务器程序设计范式7 预先创建线程,以互斥锁上锁方式保护accept
- Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)
- Java线程(七):锁对象Lock-同步问题更完美的处理方式 .
- Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量
- 进程(线程)间同步互斥问题(四) 三个烟鬼问题
- 线程状态,匿名内部类创建方式,同步锁,死锁
- Java并发原语——线程、互斥与同步
- 调用CreateMutex创建一个有名的互斥器对象