临界区,互斥量,信号量,事件多线程总结
来源:互联网 发布:淘宝网店书籍推荐 编辑:程序博客网 时间:2024/05/01 04:09
首先是创建一个线程,注意CreateThread和_beginthreadex的区别,后者在程序中含有C语言库的情况下一样安全使用。C语言库在编写的时候没有考虑到多线程,Windows中通过创建专用内存区来解决这个问题(由_beginthreadex创建)。
CreateThread和_beginthreadex参数一样,后者最终是调用前者创建线程的。
CreatThread(安全性(NULL),堆栈大小(0),函数地址(函数名字),传入参数(i),创建后状态(0),返回线程ID(NULL))
这时前者配套的函数形式DWORD WINAPI ThreadFunc(LPVOID pm)
后者配套的函数形式unsigned int __stdcall ThreadFunc(void* pm)
临界区:
注意不可以跨进程使用,不是内核对象,占用资源比较少,”线程所有权问题“只能解决”互斥问题“不可以解决“同步问题”
CRITICAL_SECTION g_csThread;//创建临界区InitializeCriticalSection(&g_csThread)//使用前初始化临界区EnterCriticalSection(&g_csThread)//进入临界区LeaveCriticalSection(&g_csThread)//离开临界区DeleteCriticalSection(&g_csThread)//用完了删除临界区
互斥量
同临界区很像,但是它是内核对象,可以跨进程使用;”线程所有权问题“只能解决”互斥问题“不可以解决“同步问题”
HANDLE handleMutex=CreateMutex(安全性(NULL),是否为当前进程所有(True),名称(NULL))ReleaseMutex(handle);//释放资源WaitForSingleObject(handle,INFINITE);//等待资源
信号量
内核对象,可以解决同步问题
CreateSemaphore(安全性(NULL),初始资源数量,最大并发数,名称(NULL));//创建信号量
<pre name="code" class="cpp">WaitForSingleObject(handle,INFINITE);//等待资源ReleaseSemaphore(句柄,增加个数,传出之前计数(NULL));OpenSemaphore(访问权,继承性,名称);
事件
内核对象,可以解决同步问题
CreateEvent(安全性(NULL),是否手动(FALSE(自动)),初始状态(TRUE为触发),事件名称(NULL));OpenEvent(访问权,继承性,名称);SetEvent(句柄);ResetEvent(句柄);
下面是一个用事件实现ABC交替执行的程序,是一个面试题,3个进程,交替执行ABC...
#include<cstdio>#include<windows.h>#include<process.h>unsigned int __stdcall Fun(void* pm);const int ThreadNum=3;const int LOOP=10;HANDLE g_hTreadEvent[ThreadNum];void main(){printf("ABC...交替执行!\n");int i=0;HANDLE handle[ThreadNum];for(i=0; i<ThreadNum; i++)g_hTreadEvent[i]=CreateEvent(NULL,FALSE,FALSE,NULL);for(i=0; i<ThreadNum; i++)handle[i]=(HANDLE)_beginthreadex(NULL,0,Fun,(void*)i,0,NULL);SetEvent(g_hTreadEvent[0]);WaitForMultipleObjects(ThreadNum,handle,TRUE,INFINITE);for(i=0;i<ThreadNum;i++){CloseHandle(handle[i]);CloseHandle(g_hTreadEvent);}}unsigned int __stdcall Fun(void* pm){int num=(int)(pm);for(int i=0; i<LOOP;i++){ WaitForSingleObject(g_hTreadEvent[num],INFINITE); printf(" %c ",num+'A'); if(num+1==ThreadNum) printf("\n"); SetEvent(g_hTreadEvent[(num+1)%ThreadNum]);//%ThreadNum}return 0;}
事件,临界区和互斥量,信号量都可以解决单生产者,消费者,缓冲区
多生产者,消费者,缓冲区,信号量解决最好
下面是事件解决单生产者,消费者,缓冲区
//1生产者 1消费者 1缓冲区//使用二个事件,一个表示缓冲区空,一个表示缓冲区满。//再使用一个关键段来控制缓冲区的访问#include <stdio.h>#include <process.h>#include <windows.h>//设置控制台输出颜色BOOL SetConsoleColor(WORD wAttributes){ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) return FALSE; return SetConsoleTextAttribute(hConsole, wAttributes);}const int END_PRODUCE_NUMBER = 10; //生产产品个数int g_Buffer; //缓冲区//事件与关键段CRITICAL_SECTION g_cs;HANDLE g_hEventBufferEmpty, g_hEventBufferFull;//生产者线程函数unsigned int __stdcall ProducerThreadFun(PVOID pM){ for (int i = 1; i <= END_PRODUCE_NUMBER; i++) { //等待缓冲区为空 WaitForSingleObject(g_hEventBufferEmpty, INFINITE); //互斥的访问缓冲区 EnterCriticalSection(&g_cs); g_Buffer = i; printf("生产者将数据%d放入缓冲区\n", i); LeaveCriticalSection(&g_cs); //通知缓冲区有新数据了 SetEvent(g_hEventBufferFull); } return 0;}//消费者线程函数unsigned int __stdcall ConsumerThreadFun(PVOID pM){ volatile bool flag = true; while (flag) { //等待缓冲区中有数据 WaitForSingleObject(g_hEventBufferFull, INFINITE); //互斥的访问缓冲区 EnterCriticalSection(&g_cs); SetConsoleColor(FOREGROUND_GREEN); printf(" 消费者从缓冲区中取数据%d\n", g_Buffer); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); if (g_Buffer == END_PRODUCE_NUMBER) flag = false; LeaveCriticalSection(&g_cs); //通知缓冲区已为空 SetEvent(g_hEventBufferEmpty); Sleep(10); //some other work should to do } return 0;}int main(){ printf(" 生产者消费者问题 1生产者 1消费者 1缓冲区\n"); printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); InitializeCriticalSection(&g_cs); //创建二个自动复位事件,一个表示缓冲区是否为空,另一个表示缓冲区是否已经处理 g_hEventBufferEmpty = CreateEvent(NULL, FALSE, TRUE, NULL); g_hEventBufferFull = CreateEvent(NULL, FALSE, FALSE, NULL); const int THREADNUM = 2; HANDLE hThread[THREADNUM]; hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL); WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE); CloseHandle(hThread[0]); CloseHandle(hThread[1]); //销毁事件和关键段 CloseHandle(g_hEventBufferEmpty); CloseHandle(g_hEventBufferFull); DeleteCriticalSection(&g_cs); return 0;}
代码来自http://www.itmian4.com/forum.php?mod=forumdisplay&fid=94&filter=typeid&typeid=127
推荐一下很好的一个网站!
0 0
- 临界区,互斥量,信号量,事件多线程总结
- C++多线程 互斥锁 信号量 事件 临界区
- 临界区 互斥量 信号量 事件
- 临界区、互斥量、信号量、事件
- 互斥量,临界区,事件,信号量
- 临界区、互斥量、信号量、事件
- 临界区 事件 互斥锁 信号量 编程总结
- 事件 信号量 互斥锁 临界区总结
- 临界区,互斥量,信号量,事件的区别
- 临界区,互斥量,信号量,事件的区别
- Windows 临界区,内核事件,互斥量,信号量
- 同步机制 ----临界区、互斥量、信号量、事件
- 临界区,互斥量,信号量,事件的区别
- Windows 临界区,内核事件,互斥量,信号量。
- Windows 临界区,内核事件,互斥量,信号量
- Windows 临界区,内核事件,互斥量,信号量。
- Windows 临界区,内核事件,互斥量,信号量。
- 关于互斥锁,临界区,互斥量,信号量,事件
- flex 4.6 安装小结
- JS截取字符串substr 和 substring方法的区别
- 【总结】Oracle sql 中的字符(串)替换与转换
- Linux常用shell命令
- Android中的Environment.getExternalStorageState使用
- 临界区,互斥量,信号量,事件多线程总结
- 【面试准备】字符串反序
- SEO在未来的发展是否会变更方向
- IOCP十:Client退出后投递WSARecv
- c#的 UDP接收
- 将大型 Page Blob 的页范围进行分段
- oracle 更改时间类型的默认显示方式(从实践中学习Oracle SQL学习笔记 第一章)
- POJ 2663
- 解决linux cp: omitting directory