C++多线程 互斥锁 信号量 事件 临界区
一、互斥锁
1、先熟悉熟悉API
1,创建互斥锁,并反正一个句柄
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针
BOOLbInitialOwner, // 初始化互斥对象的所有者,一般设置为FALSE
LPCTSTRlpName // 互斥对象名
);2,释放互斥对象的控制权
BOOL ReleaseMutex(
HANDLE hMutex //已创建Mutex的句柄
);3,打开互斥锁,返回句柄
HANDLE OpenMutex(
DWORDdwDesiredAccess, // 互斥体的访问权限
BOOLbInheritHandle, //如希望子进程能够继承句柄,则为TRUE
LPCTSTRlpName // 互斥锁名字
);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);//开启线程1CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2system("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);//开启线程1CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2system("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);//开启线程1CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)address2, NULL, NULL, NULL);//开启线程2system("pause");DeleteCriticalSection(&g_cs);return 0;
}
ps:小例中,address1被临界区一直占用到到address1退出,address2才能进入临界区,进行直到退出,与mutex交替执行不同,临界区比较简单且最易用。
更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~
C++多线程 互斥锁 信号量 事件 临界区相关推荐
- java多线程互斥锁_浅谈Java多线程互斥锁
为了解决竞争条件带来的问题,我们可以对资源上锁.多个线程共同读写的资源称为共享资源,也叫临界资源.涉及操作临界资源的代码区域称为临界区(Critical Section).同一时刻,只能有一个线程进入 ...
- java多线程- 互斥锁 自旋锁
如果一个资源会被不同的线程访问修改,那么我们把这个资源叫做临界资源(<操作系统>),那么对于该资源访问修改相关的代码就叫做临界区.引入互斥锁即解决多个线程之间共享同一个共享资源,这是多线程 ...
- 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)...
参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...
- python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))...
昨日内容回顾 python中启动子进程 并发编程 并发 :多段程序看起来是同时运行的 ftp 网盘 不支持并发 socketserver 多进程 并发 异步 两个进程 分别做不同的事情 创建新进程 j ...
- 【C++】多线程互斥锁、条件变量
我们了解互斥量和条件变量之前,我们先来看一下为什么要有互斥量和条件变量这两个东西,了解为什么有这两东西之后,理解起来后面的东西就简单很多了!!! 先来看下面这段简单的代码: int g_num = 0 ...
- day034 锁,信号量,事件,队列,子进程与子进程通信,生产者消费者模型,joinableQueue...
进程锁 #加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全. 虽然可以用文件共享数据实现进程间通信,但问题是: 1 ...
- 【Linux】多线程--互斥锁
文章目录 前言 基础概念 互斥量mutex 多线程模拟抢票(没加锁情况) 为何多线程访问临界资源是不安全 互斥锁相关接口 多线程模拟抢票(有加锁) 互斥锁实现的基本原理 前言 为什么线程需要同步和互斥 ...
- Windwos下的互斥锁,事件以及事件的手动重置和自动重置的区别
事件的自动重置:两个线层同时访问一个函数,该函数会对全局变量进行操作,用事件进行互斥,假设这个事件初始化有信号 在经过WAITFORSIGALOBJECT()后事件就会变为没有信号,另外一个线程无 ...
- Python多线程--互斥锁、死锁
1.互斥锁 为解决资源抢夺问题,使用mutex = Threading.Lock()创建锁,使用mutex.acquire()锁定,使用mutex.release()释放锁. 代码一: import ...
最新文章
- ModuleNotFoundError: No module named 'tools.nnwrap' pytorch 安装
- 【Manning新书】可解释人工智能: 构建可解释机器学习系统
- Jquery 获取对象的几种方式介绍
- 2021高考成绩微信查询方法6,2021年高考成绩查询时间、入口及方法
- suse linux 查看内存,Suse linux查询内存大小的指令是什么?
- 帮别人改的代码 我也不知道他爬的什么 记录下
- 一个表的信息插入到另一个表里面,如果遇到重复的就覆盖
- 陆正耀为瑞幸数据造假道歉:非常自责 会全力挽回损失
- 意见簿---在批评中成长
- jquery显示与隐藏效果
- 我没钱 如何推广自己的网站
- go语言中金币分配训练--pm
- 高质量编程之编译警告级别
- python音频频谱分析软件_SpectrumView(音频频谱分析软件)
- 服务器gpt分区不能安装系统,安装Win10原版系统提示“Windows无法安装到GPT分区形式磁盘”怎么办...
- 区块链与金融基础设施——兼论Facebook Libra
- 2020.4.15华为实习招聘笔试题第三题
- Continuous Passive Motion (CPM)持续性被动运动
- 如何备份管家婆软件数据?3种方法详解
- 李兴华-JAVA10 第1章: Java语言简介