C++基础学习之16 - 多线程与互斥锁
来源:互联网 发布:黑客帝国矩阵屏保 编辑:程序博客网 时间:2024/06/05 04:55
熟悉Linux的童鞋都对多进程比较熟,Linux下的 fork也有很多教程介绍,但这不是我们本节的重点,我们在这里主要讲的是多线程。
相对于进程来讲,线程 是一个轻量级的概念,一个进程包含多个线程(至少1个)。
线程有自己的堆栈和局部变量,但没有内存空间,而是共享进程的内存空间。
这种共享内存机制 优点在于通过数据共享的快速访问,同样这种机制 也会导致 一个线程死掉的时候可能导致整个程序崩溃。
那么多线程之间如何 有效共享一段数据呢?
一. 临界区(Critical Section)
临界区 是Windows下专用的一种同步机制,一次只允许一个线程使用的共享资源,如果已经有线程进入了临界区,则其它线程必须等待。临界区 类似一种原子操作。
void thread_func() { // 进入临界区 EnterCriticalSection(); // do something // 离开临界区 LeaveCriticalSection(); }
临界区 通过代码段的方式来控制 内存或数据的共享,其实现较为简单。
二. 互斥锁(Mutex)
互斥锁 与临界区类似,也是确保同一时刻只能由一个线程进行访问,其区别在于:
1. Mutex可以跨进程,临界区只能在同一进程中使用;
2. Mutex是内核对象(核心态操作),速度慢;临界区是非内核对象(用户态操作),速度快;
3. Mutex和临界区在Windows平台都下可用,Linux下只能用 Mutex。
对比一下在Linux和Windows平台下的Mutex使用代码:
/** Linux*/#include <pthread.h>pthread_mutex_t m_mutex;pthread_mutex_init(&m_Mutex, NULL);int nRet = pthread_mutex_lock(&m_Mutex);…… // do somethingnRet = pthread_mutex_unlock(&m_Mutex);pthread_mutex_destroy(&m_Mutex); // 销毁/** Windows*/#include "windows.h"HANDLE m_Mutex = CreateMutex(NULL, FALSE, NULL);if( WAIT_OBJECT_0 == WaitForSingleObject(m_Mutex, INFINITE) ){ …… // do something ReleaseMutex(m_Mutex);}CloseHandle(m_Mutex); // 销毁
三. 信号量(Semaphore)
信号量 是Mutex的一种扩展形式,信号量可以看作是一个资源池,当值大于0时,使用者可以锁定并使用,当小于0时,必须等待有新的资源释放才能去访问。
当设置信号量最大值为1时,信号量退化为Mutex。
/** Linux*/#include <pthread.h>#include <semaphore.h>void *thread_func() // 线程函数{ for(int i=0;i<50;i++) { sem_wait(&sem); //V操作,信号量-1 printf("num %d: Now i come!",i); sem_post(&sem); //P操作,信号量+1 printf("num %d: Now i leave!",i); }}void main(){ sem_t sem; sem_init(&sem,0,5); // 信号量值为5 - 理解为保证每个时刻最多5个人进入房间 pthread_t th[5]; for(int i=0;i<5;i++) pthread_create(&th[i], NULL, thread_func, NULL); // 销毁 pthread_join(&th[i], NULL); sem_destroy(&sem); // 关闭unnamed信号量(对应named信号量用sem_close)}/** Windows*/#include "windows.h"HANDLE hSemp = CreateSemaphore(NULL, 2, 2, NULL); // 创建信号量对象 WaitForSingleObject(hSemp, INFINITE); // V操作,进入信号量ReleaseSemaphore(hSemp, 1, NULL); // P操作,释放信号量CloseHandle(hSemp); // 关闭信号量对象
四. 事件(Event)
事件 与临界区一样,也是 Windows下独有的一种概念,事件是内核对象,多用于线程间通信,可以跨进程同步,主要用到三个函数:CreateEvent,OpenEvent,SetEvent,ResetEvent。
OpenEvent与CreateEvent(创建)类似,是打开一个有名事件,我们重点说明另外两个函数:
SetEvent:每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态;
ResetEvent:事件重置,回到未触发状态(注:bManualReset可以设置触发后自动重置)。
#include <windows.h>HANDLE g_Event = CreateEvent(NULL,false,false,NULL); // HANDLE CreateEvent(LPSECURITY_ATTRIBUTE SlpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName);SetEvent(g_Event);// 线程绑定的函数返回值和参数是确定的,而且一定要__stdcallint __stdcall threadFun(){ WaitForSingleObject(g_Event, INFINITE); // 等待事件触发 SetEvent(g_Event); // 设置事件为触发状态,后面的线程再用 return 0;}int main(){ HANDLE th1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, NULL, 0, NULL); // _beginthreadex可以调用__stdcall HANDLE th2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, NULL, 0, NULL); // 与CreateThread不同 WaitForSingleObject(hth1, INFINITE); // - key point WaitForSingleObject(hth2, INFINITE); CloseHandle(g_Event); // 关闭事件 return 0;}这样,整个逻辑变成,哪个线程触发事件,就可以执行自己的代码段,而其他线程必须等待该事件释放,从而达到同步的效果。
- C++基础学习之16 - 多线程与互斥锁
- Linux C基础学习之autoconf与automake
- C++基础学习之7 - 与C程序对话
- 多线程基础学习十四:ReadWriteLock与ReentrantReadWriteLock
- java基础学习之 多线程 概述
- Java多线程基础之进程与线程
- Linux C 多线程编程之互斥锁与条件变量
- 多线程之互斥锁(By C++)与多进程
- 多线程之 NSOperation 与 NSOperationQueue 的基本操作 适合基础学习
- C语言学习之基础学习01
- python学习之异常与多线程
- C语言多线程基础-01-线程的创建与销毁
- 黑马程序员IOS基础---C语言学习之变量与内存及重要的scanf函数
- 黑马程序员IOS基础---C语言学习之字符串与字符串数组
- (五)JNI学习之C语言基础,typedef与宏定义
- 学习笔记之C语言基础篇
- 嵌入式linux-C学习之基础
- iphone开发基础之objective-c学习
- C++基础学习之15 - 消息机制
- Oracle分析函数--排序
- 如何访问虚拟机中的架设的Web服务器(学习笔记)
- character filter
- 【Java笔记】构造方法链
- C++基础学习之16 - 多线程与互斥锁
- 读书记录2(仅个人)- 树的各种使用
- CSS知识点
- Web性能优化分析
- 第四十讲项目6-三色球问题
- 插入排序递归法
- 用Visual studio和Xamarin构建移动开发平台
- 剑灵的空气扭曲
- 关于通信中数据接收的处理方法讨论