信号量机制在WINDOWS编程中的实际应用
2008-03-11 10:18
253 查看
同步问题就是因为线程/进程 间异步执行访问共享数据而引起的数据冲突的问题(经典的例子:生产者与消费者问题),windows提供了一些同步对象来解决此类问题,包括:临界区对象、互斥体对象、事件对象、信号量对象,下面将对这些同步对象进行说明举例。
Win32 API提供了一组能使线程阻塞其自身执行的等待函数。这些函数在其参数中的一个或多个同步对象产生了信号,或者超过规定的等待时间才会返回。
在等待函数未返回时,线程处于等待状态,此时线程只消耗很少的CPU时间。使用等待函数既可以保证线程的同步,又可以提高程序的运行效率。
最常用的等待函数是:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); //监测单个的同步对象状态
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WaitForMultipleObject(DWORD nCount,CONST HANDLE *lpHandles,BOOL bWaitAll,DWORD dwMilliseconds); //同时监测多个同步对象
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
这两个函数是线程同步关键的等待函数。
1)临界区对象
临界区对象可以保证同一时刻只有一个线程执行一段访问共享数据结构的代码区(临界区),当一个线程进入临界区,
只有等待该线程执行完临界区代码的指令后,其它线程才能访问临界区的代码,这样就能够有效地保护共享数据的完整性。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class CShareData
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
char m_buf[MAX];
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
CRITICAL_SECTION m_cs;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
CShareData()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
//初始化临界区
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
InitializeCriticalSection(&m_cs);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
...
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
~CShareData()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
read()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxh<br/>4000<br/>ighlighting/OutliningIndicators/InBlock.gif)
EnterCriticalSection(&m_cs);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
....
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LeaveCriticalSection(&m_cs);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
write()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
EnterCriticalSection(&m_cs);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
....
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LeaveCriticalSection(&m_cs);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
2)事件对象
事件对象有两种状态,无信号状态和有信号状态,在线程访问某一资源之前,需要
等待某一事件发生时,使用事件对象最为适合。
实例:
该实例保证先执行线程1(threadFun1),后执行线程2(threadFun2)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
HANDLE hEvent1 = NULL;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
HANDLE hEvent2 = NULL;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
char g_buf[10] = ...{0};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WINAPI threadFun1(LPVOID pParam)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
WaitForSingleObject(hEvent1,INFINITE);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
for(int i=0;i<10;i++)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
g_buf = 'a';
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sleep(200);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printf("thread1: %s ",g_buf);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
SetEvent(hEvent2);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WINAPI threadFun2(LPVOID pParam)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
//当该函数返回后事件对象自动设置为无信号状态,这样其他线程也将被挂起
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
WaitForSingleObject(hEvent2,INFINITE);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
for(int i=0;i<10;i++)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
g_buf = 'b';
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sleep(200);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printf("thread2: %s ",g_buf);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
//SetEvent(hEvent);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int main(int argc, char* argv[])
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
SetEvent(hEvent1);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
HANDLE hThread1 = CreateThread(NULL,0,threadFun1,0,0,0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
HANDLE hThread2 = CreateThread(NULL,0,threadFun2,0,0,0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sleep(5000);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
printf("%s ",g_buf);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
3)信号量对象
信号对象允许同时对多个线程共享资源进行访问,在创建对象时指定最大可同时访问的线程数。
当一个线程申请访问成功后,信号对象中的计数器减一,调用ReleaseSemaphore函数后,
信号对象中的计数器加一。其中,计数器值大于或等于0,但小于或等于创建时指定的最大值。
如果一个应用在创建一个信号对象时,将其计数器的初始值设为0,就阻塞了其他线程,保护了资源。
等初始化完成后,调用ReleaseSemaphore函数将其计数器增加至最大值,则可进行正常的存取访问。
经常使用的一个简单的应用例子是判断一个程序是否已经运行了,该内核对象可在不同进程间访问。
实例:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
HANDLE hSemaphore;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WINAPI threadFun1(LPVOID pParam)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
WaitForSingleObject(hSemaphore,INFINITE);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
MessageBox(NULL,"thread1","hint",MB_OK);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
ReleaseSemaphore(hSemaphore,1,NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WINAPI threadFun2(LPVOID pParam)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
WaitForSingleObject(hSemaphore,INFINITE);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
MessageBox(NULL,"thread2","hint",MB_OK);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
ReleaseSemaphore(hSemaphore,1,NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
DWORD WINAPI threadFun3(LPVOID pParam)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
WaitForSingleObject(hSemaphore,INFINITE);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
MessageBox(NULL,"thread3","hint",MB_OK);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
ReleaseSemaphore(hSemaphore,1,NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
int main(int argc, char* argv[])
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
HANDLE hThread1 = CreateThread(NULL,0,threadFun1,0,0,0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
HANDLE hThread2 = CreateThread(NULL,0,threadFun2,0,0,0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
HANDLE hThread3 = CreateThread(NULL,0,threadFun3,0,0,0);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sleep(100000);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return 0;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
4)互斥体对象
互斥体对象与临界区对象相似,只是临界区对象只适用于同一个进程中。
相关文章推荐
- 信号量机制在WINDOWS编程中的实际应用
- Microsoft 用于构建面向服务的应用程序的统一编程模型--Indigo简介 - WCF(WindowsCommunicationFoundation)构建面向服务的分布式应用
- 计算机理论在实际编程中的应用之我见
- 基于visual c++之windows核心编程代码分析(62)读取本地已登录的QQ号及应用代码
- Windows编程基础一:Windows应用的基本概念
- windows编程之应用层的线程同步
- 基于visual c++之windows核心编程代码分析(62)读取本地已登录的QQ号及应用代码
- 基于visual c++之windows核心编程代码分析(62)读取本地已登录的QQ号及应用代码
- DSAPI多功能组件编程应用-文件类-添加删除程序到Windows启动
- 在编程的世界中,如何高效地学习理论知识,应用理论知识来解决实际生产中的问题
- word编程补充-关于word打印的实际应用
- C#实验8Windows应用编程
- Windows 系统编程初探 (六)结构化异常处理之三:SEH 的简单应用
- 编程在线Windows 8客户端----即将登陆微软Windows Store应用商店
- windows编程之MFC创建单文档应用之菜单添加
- 开发应用识别软件遇到的一些windows编程技能
- Cookie和Session的基础知识+高级编程+实际开发中的应用(经典)
- WF 的实际应用:Windows Workflow Foundation 应用程序最佳实践
- 《windows应用高级编程-C#编程篇》书中程序的小问题及改进
- windows多线程应用编程注意事项