C++多线程 互斥锁 信号量 事件 临界区
来源:互联网 发布:java zip打包下载 编辑:程序博客网 时间:2024/05/22 04:35
一、互斥锁
1、先熟悉熟悉API
1,创建互斥锁,并反正一个句柄HANDLE CreateMutex(LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针BOOLbInitialOwner, // 初始化互斥对象的所有者,一般设置为FALSELPCTSTRlpName // 互斥对象名);2,释放互斥对象的控制权BOOL ReleaseMutex(HANDLE hMutex //已创建Mutex的句柄);3,打开互斥锁,返回句柄HANDLE OpenMutex(DWORDdwDesiredAccess, // 互斥体的访问权限BOOLbInheritHandle, //如希望子进程能够继承句柄,则为TRUELPCTSTRlpName // 互斥锁名字);4,等待目标返回DWORD WaitForSingleObject(HANDLE hHandle, //目标句柄DWORD dwMilliseconds //等待时间 ,毫秒记,INFINITE为永久等待);
一个简单的互斥锁例子来实现多线程同步
#include<Windows.h>#include<stdlib.h>#include<iostream>using namespace std;static int g_count = 100;class Lock{public: Lock(char*szName) { hd = OpenMutex(MUTEX_ALL_ACCESS, NULL, (LPCWSTR)szName); WaitForSingleObject(hd, INFINITE); Sleep(1500);//测试用:等待1.5秒,正式类中不应有 } ~Lock() { ReleaseMutex(hd); } static bool InitLock(char*szName) { if (!OpenMutex(MUTEX_ALL_ACCESS, NULL, (LPCWSTR)szName)) { if (!CreateMutex(NULL, NULL, (LPCWSTR)szName)) return false; return true; } return false; } HANDLE hd;};UINT address1(LPVOID lparam){ while (1) { Lock lc("_temp_lock"); cout << g_count-- << "---" << "address1" << endl; }}UINT address2(LPVOID lparam){ while (1) { Lock lc("_temp_lock"); cout << g_count-- << "---" << "address2" << endl; }}int main(int argc, char*argv[]){ if(!Lock::InitLock("_temp_lock"))//创建互斥锁失败 return -1; CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address1, NULL, NULL, NULL);//开启线程1 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2 system("pause"); return 0;}
原理浅析:Lock::InitLock()来创建互斥锁,在本demo中,同步是按照CreateThread的创建顺序。创建了一个Lock类,当生成对象的时候就等待,一旦当互斥锁没有控制权,等待即结束,便向下执行,对象析构的时候就释放控制权,以此类推循环。
ps:mutex作用范围在系统层,使用mutex效率并不是太高,使用临界区(作用范围在进程)效率比较高
二、信号量
1,先熟悉熟悉API
CreateSemaphore() 创建一个信号量 OpenSemaphore() 打开一个信号量 ReleaseSemaphore() 释放信号量 WaitForSingleObject() 等待信号量
2,举个简单的小例子
#include <stdio.h> #include <Windows.h> #define THREAD_NUM 20#define SEM_NAME "THREAD_SEMAPHORE"HANDLE g_hSem = NULL;HANDLE g_hThread[THREAD_NUM];void WINAPI ThreadFun(void* param){ printf("进入线程: %u,并等待\n", GetCurrentThreadId()); WaitForSingleObject(g_hSem, INFINITE); printf("线程: %u 获得信号量\n", GetCurrentThreadId()); long dwSem = 0; if (!ReleaseSemaphore(g_hSem, 1, &dwSem)) return; printf("目前资源数:%u\n", dwSem);}int main(int argc, char*argv[]){ g_hSem = CreateSemaphoreA(NULL, 0, 5, SEM_NAME); g_hSem = OpenSemaphoreA(SEMAPHORE_MODIFY_STATE, FALSE, SEM_NAME); for (int i = 0; i < THREAD_NUM; ++i) { DWORD dwThreadID = 0; g_hThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFun, NULL, 0, &dwThreadID); } WaitForMultipleObjects(THREAD_NUM, g_hThread, TRUE, INFINITE); printf("全部执行完了\n"); return 0;}
ps:信号量可以说在平常的使用中用的比较少,一般的用途在控制并发线程数量,抢占资源问题。
三、事件
1,先熟悉熟悉API
HANDLE CreateEvent( //创建事件LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性BOOL bManualReset,// 复位方式BOOL bInitialState,// 初始状态LPCTSTR lpName // 对象名称);HANDLE OpenEvent( //打开事件DWORD dwDesiredAccess,BOOL bInheritHandle,LPCTSTR lpName);BOOL ResetEvent(//事件对象设置为无信号状态。HANDLE hEvent);BOOL SetEvent(HANDLE hEvent);//事件对象设置为有信号状态。 BOOL PulseEvent(HANDLE hEvent)//事件对象设置为有信号状态,脉冲一个事件WaitForSingleObject() 等待信号量
2,举个简单的小例子
#include <stdio.h>#include <Windows.h>HANDLE g_hEvent;UINT address1(LPVOID lparam){ printf("进入线程了,等待5秒\n"); WaitForSingleObject(g_hEvent, INFINITE); printf("等待结束了,向下执行了!\n"); return 0;}UINT address2(LPVOID lparam){ Sleep(5000); SetEvent(g_hEvent); return 0;}int main(int argc, char*argv[]){ g_hEvent=CreateEvent(NULL, true, FALSE, NULL); ResetEvent(g_hEvent); CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address1, NULL, NULL, NULL);//开启线程1 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2 system("pause"); return 0;}
ps:本小例模拟了的两个线程间的同步,address2来控制address1的执行,事件在多线程程序中的应用比较多,比较重要,定要熟练掌握。
四、临界区
1,先熟悉熟悉API
void InitializeCriticalSection(//初始化临界区 LPCRITICAL_SECTION lpCriticalSection); void WINAPI DeleteCriticalSection( //删除临界区 _Inout_ LPCRITICAL_SECTION lpCriticalSection);VOID WINAPI EnterCriticalSection( //进入临界区 __inout LPCRITICAL_SECTION lpCriticalSection); VOID WINAPI LeaveCriticalSection(//离开临界区 _Inout_ LPCRITICAL_SECTION lpCriticalSection );
2,举个简单的小例子
#include <stdio.h>#include <Windows.h>CRITICAL_SECTION g_cs;int g_nIndex = 20;UINT address1(LPVOID lparam){ while(true) { if (10 == g_nIndex) return 1; EnterCriticalSection(&g_cs); printf("address111线程,index=%d\n",g_nIndex); g_nIndex--; LeaveCriticalSection(&g_cs); } return 0;}UINT address2(LPVOID lparam){ while (true) { if (0 == g_nIndex) return 1; EnterCriticalSection(&g_cs); printf("address222线程,index=%d\n", g_nIndex); --g_nIndex; LeaveCriticalSection(&g_cs); } return 0;}int main(int argc, char*argv[]){ InitializeCriticalSection(&g_cs); CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address1, NULL, NULL, NULL);//开启线程1 CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2 system("pause"); DeleteCriticalSection(&g_cs); return 0;}
ps:小例中,address1被临界区一直占用到到address1退出,address2才能进入临界区,进行直到退出,与mutex交替执行不同,临界区比较简单且最易用。
更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~
0 0
- C++多线程 互斥锁 信号量 事件 临界区
- 临界区,互斥量,信号量,事件多线程总结
- 关于互斥锁,临界区,互斥量,信号量,事件
- 关于互斥锁,临界区,互斥量,信号量,事件
- 互斥锁 临界区 信号量 事件的区别
- 临界区 事件 互斥锁 信号量 编程总结
- 互斥锁 临界区 信号量 事件的区别
- 事件 信号量 互斥锁 临界区总结
- 互斥锁 临界区 信号量 事件的区别
- 多线程同步方法:临界区、事件、信号量、互斥对象
- 临界区 互斥量 信号量 事件
- 临界区 互斥体 信号量 事件
- 临界区、互斥量、信号量、事件
- 互斥量,临界区,事件,信号量
- 临界区、互斥量、信号量、事件
- 多线程实现生产者消费者问题 详细注释 事件+临界区 信号量+临界区2种方法
- C++互斥锁 临界区 信号量 事件的区别总结
- 临界区,互斥量,信号量,事件的区别
- Linux命令基础15-top命令
- 内联函数的意义和使用
- Linux 命令之系统管理(长期维护)
- 红黑树与AVL树
- 数据结构(7)之红—黑树
- C++多线程 互斥锁 信号量 事件 临界区
- centos配置hadoop伪分布式环境
- 自定义设置hr的颜色
- java基础改学C++(八)运算符重载
- Python中用print方法向文件中写入内容
- hdu5978(概率思维题)
- 汪国新关公百图精品展在台北国父纪念馆隆重举行
- 数据结构(8)之堆
- Dubbo实战之具体应用