多线程第六篇:信号量
来源:互联网 发布:淘宝女包新款 编辑:程序博客网 时间:2024/05/12 09:04
信号量及信号量上的操作是E.W.Dijkstra 在1965年提出的一种解决同步、互斥问题的较通用的方法,并在很多操作系统中得以实现, Linux改进并实现了这种机制。
信号量(semaphore )实际是一个整数,它的值由多个进程进行测试(test)和设置(set)。就每个进程所关心的测试和设置操作而言,这两个操作是不可中断的,或称“原子”操作,即一旦开始直到两个操作全部完成。测试和设置操作的结果是:信号量的当前值和设置值相加,其和或者是正或者为负。根据测试和设置操作的结果,一个进程可能必须睡眠,直到有另一个进程改变信号量的值。
信号量可用来实现所谓的“临界区”的互斥使用,临界区指同一时刻只能有一个进程执行其中代码的代码段。为了进一步理解信号量的使用,下面我们举例说明。
假设你有很多相互协作的进程,它们正在读或写一个数据文件中的记录。你可能希望严格协调对这个文件的存取,于是你使用初始值为1的信号量,在这个信号量上实施两个操作,首先测试并且给信号量的值减1,然后测试并给信号量的值加1。当第一个进程存取文件时,它把信号量的值减1,并获得成功,信号量的值现在变为0,这个进程可以继续执行并存取数据文件。但是,如果另外一个进程也希望存取这个文件,那么它也把信号量的值减1,结果是不能存取这个文件,因为信号量的值变为-1。这个进程将被挂起,直到第一个进程完成对数据文件的存取。当第一个进程完成对数据文件的存取,它将增加信号量的值,使它重新变为1,现在,等待的进程被唤醒,它对信号量的减1操作将获得成功。
上述的进程互斥问题,是针对进程之间要共享一个临界资源而言的,信号量的初值为1。实际上,信号量作为资源计数器,它的初值可以是任何正整数,其初值不一定为0或1。另外,如果一个进程要先获得两个或多个的共享资源后才能执行的话,那么,相应地也需要多个信号量,而多个进程要分别获得多个临界资源后方能运行,这就是信号量集合机制.
首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便。下面是这几个函数的原型和使用说明。
第一个 CreateSemaphore
函数功能:创建信号量
函数原型:
HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
函数说明:
第一个参数表示安全控制,一般直接传入NULL。
第二个参数表示初始资源数量。
第三个参数表示最大并发数量。
第四个参数表示信号量的名称,传入NULL表示匿名信号量。
第二个 OpenSemaphore
函数功能:打开信号量
函数原型:
HANDLE OpenSemaphore( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
函数说明:
第一个参数表示访问权限,对一般传入SEMAPHORE_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示信号量句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。
第三个 ReleaseSemaphore
函数功能:递增信号量的当前资源计数
函数原型:
BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
函数说明:
第一个参数是信号量的句柄。
第二个参数表示增加个数,必须大于0且不超过最大资源数量。
第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。
注意:当前资源数量大于0,表示信号量处于触发,等于0表示资源已经耗尽故信号量处于末触发。在对信号量调用等待函数时,等待函数会检查信号量的当前资源计数,如果大于0(即信号量处于触发状态),减1后返回让调用线程继续执行。一个线程可以多次调用等待函数来减小信号量。
最后一个 信号量的清理与销毁
由于信号量是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。
信号量其实就是人们常说的PV操作.p操作是计数器+1,即ReleaseSemaphore函数,而v操作是-1,即waitforsignalobject操作.
我们先来一个简单的,用信号量实现线程间互斥:
#include <iostream>#include <windows.h>#include <process.h>int g_count = 0;HANDLE g_ThreadEvent , g_threadMutex, g_threadSemaphore ;unsigned int __stdcall ThreadFun (void * pthread_num){ //WaitForSingleObject(g_ThreadEvent,INFINITE); WaitForSingleObject( g_threadSemaphore ,INFINITE ); int num = *(( int *)pthread_num ); //std::cout<<"线程号:"<<GetCurrentThreadId()<<"线程编号为地址:"<<&num<<"线程编号"<<num<<"全局资源编号为:"<<++g_count<<std::endl; std:: cout<< "线程编号" << num<< "全局资源编号为:" <<++ g_count<< std ::endl ; //std::cout<<"进程号:"<<(int)getpid()<<"线程号:"<<GetCurrentThreadId()<<std::endl; //SetEvent(g_ThreadEvent); // ReleaseMutex(g_threadMutex); ReleaseSemaphore( g_threadSemaphore ,1,NULL ); return 0;}int main (){ const int thread_num = 10; g_threadSemaphore = CreateSemaphore (NULL ,1,1, NULL); //g_ThreadEvent = CreateEvent(NULL,false,false,NULL); //g_threadMutex = CreateMutex(NULL,false,NULL); //SetEvent(g_ThreadEvent); //在此处触发事件 HANDLE handle [thread_num ]; for ( int i = 0 ; i <thread_num ; ++ i ){ handle [i ] = ( HANDLE) _beginthreadex (NULL ,0, ThreadFun,& i ,0,NULL ); //WaitForSingleObject(g_threadMutex,INFINITE); } //等待所有创建的子线程都执行完. WaitForMultipleObjects( thread_num ,handle , true, INFINITE); //CloseHandle(g_ThreadEvent); //CloseHandle(g_threadMutex); CloseHandle( g_threadSemaphore ); return 0;}
好了,我们来实现一个信号量进行同步的操作吧.
#include <iostream>#include <windows.h>#include <process.h>int g_count = 0;HANDLE g_ThreadEvent , g_threadMutex, g_threadSemaphore ;unsigned int __stdcall ThreadFun (void * pthread_num){ //WaitForSingleObject(g_ThreadEvent,INFINITE); //WaitForSingleObject(g_threadSemaphore,INFINITE); int num = *(( int *)pthread_num ); //std::cout<<"线程号:"<<GetCurrentThreadId()<<"线程编号为地址:"<<&num<<"线程编号"<<num<<"全局资源编号为:"<<++g_count<<std::endl; std:: cout<< "线程编号" << num<< "全局资源编号为:" <<++ g_count<< std ::endl ; //std::cout<<"进程号:"<<(int)getpid()<<"线程号:"<<GetCurrentThreadId()<<std::endl; //SetEvent(g_ThreadEvent); // ReleaseMutex(g_threadMutex); ReleaseSemaphore( g_threadSemaphore ,1,NULL ); return 0;}int main (){ const int thread_num = 10; g_threadSemaphore = CreateSemaphore (NULL ,0,1, NULL); //g_ThreadEvent = CreateEvent(NULL,false,false,NULL); //g_threadMutex = CreateMutex(NULL,false,NULL); //SetEvent(g_ThreadEvent); //在此处触发事件 HANDLE handle [thread_num ]; for ( int i = 0 ; i <thread_num ; ++ i ){ handle [i ] = ( HANDLE) _beginthreadex (NULL ,0, ThreadFun,& i ,0,NULL ); //WaitForSingleObject(g_threadMutex,INFINITE); WaitForSingleObject (g_threadSemaphore , INFINITE); } //等待所有创建的子线程都执行完. WaitForMultipleObjects( thread_num ,handle , true, INFINITE); //CloseHandle(g_ThreadEvent); //CloseHandle(g_threadMutex); CloseHandle( g_threadSemaphore ); return 0;}
0 0
- 多线程第六篇:信号量
- 多线程信号量
- 多线程--信号量
- 多线程-信号量
- 第六章 信号量集
- linux多线程变成第四篇--信号量
- 使用信号量管理多线程
- C++多线程-信号量Semaphore
- C#多线程之信号量
- 多线程信号量控制
- linux多线程----信号量
- linux多线程----信号量
- windows多线程同步--信号量
- windows多线程同步--信号量
- 多线程编程之信号量
- linux多线程 --信号量
- c++ 多线程 信号量
- 【多线程】(八)信号量
- UVa:11029 Leading and Trailing
- 友情链接建设要点问题,seo站长必看
- Fragment之模仿微信界面
- Android中JNI的使用方法
- win7做WIFI热点:3分钟笔记本变无线路由器
- 多线程第六篇:信号量
- web 图片编辑应用 pixlr
- 序列函数
- SecureCRT 使用指南
- Linux系统监控工具之vmstat详解
- 高效使用Bitmaps(一) 大Bitmap的加载
- SIFT/SURF、haar特征、广义hough变换
- 网盘 网盘 通讯录 相册 文章 记事本 短信
- cygwin下vim方向键不好用的解决方案