VC++线程同步(五) 信号量使用例子

信号量(Semaphore)

信号量是内核对象,使用几个形象的例子,进行描述.

1 假设有5个位置,而外面有很多人要进来,那么当5个位置被人占用了

后,其他人就必须排队等待,每个人使用时间不同,5个占用的位置,其中有两个完成了,那么,排队的人中,最前面的两个人进行可以使用,但是最多就是5个人同时能够使用,这就是信号量.

2 例如我们在服务器中创建了一个线程池,它由5个线程组成,也就意味着,最多同时处理5个请求,一旦超过5个,那么请求就放入缓冲中,当一个或多个请求(最多5个)完成后,那么从缓冲中拿出其他的请求进行处理.

信号量的特点:

1 信号量同来对资源进行计数

2 包含一个使用计数器,一个最大资源计数器,和一个当前资源计数器

3 最大资源计数器用来控制最大的子元素

4 当前资源计数器表示当前可用的资源数量

触发规则和当前资源计数器是相关的。

触发规则:

1 如果当前资源>0则信号量处于触发状态

2 如果当前资源=0,则信号量处于未触发状态

3 系统绝对不会让当前资源技术变为负值

4 当前资源计数绝对不会大于最大资源计数

运行流程:

1 假设我们创建了一个信号量,它的最大资源计数为5,且当前资源计数

也为5(一般都是在初始化过程中间最大的资源计数值和当前资源计数值是相同的) 由于当前资源计数器大于0,说明信号量处于触发状态.

2 为了获取对被保护的资源的访问权,线程会调用wait函数,并转入信号量的句柄,在内部,等待函数会检测当前资源计数器 技术,如果大于

0(大于0触发状态)那么等待函数会将当前资源计数器减1并让调用线程

继续运行,如果等于0(未触发状态)那么系统会让线程进入等待状态(不消化cpu),当另外一个线程将信号量的当前资源计数递增时,系统会

记得哪些线程在等待,使他们编程可调度状态(并相应的递减当前资源计数)

3 线程通过releaseSemaphore来递增信号量的当前资源计数器.

来看代码:

全局变量 HANDLE g_hSem;

创建一个信号量CreateSemaphore(NULL,2,2,NULL);

参数1 windows。。权限

参数2 代表当前资源计数值

参数3 最大资源计数器,表示信号量同时可以管理2个线程

参数4 对象名...

应为创建的时候,当前的资源计数大于0,所以他是触发状态的。

创建5个线程,用5个线程竞争两个位置,体现一下竞争的激烈.

case WM_CREATE:
{
//系统中基于对话框字体的高度
int cyChar = HIWORD(GetDialogBaseUnits());
thrParams4.hwnd = hWnd;
thrParams4.cyChar = cyChar;
//创建信号量 
g_hSem = CreateSemaphore(NULL, 2, 2,NULL);
HANDLE handleEmployee1 = CreateThread(NULL, 0, ThrEmployeeProc1, &thrParams4, 0, NULL);
HANDLE handleEmployee2 = CreateThread(NULL, 0, ThrEmployeeProc2, &thrParams4, 0, NULL);
HANDLE handleEmployee3 = CreateThread(NULL, 0, ThrEmployeeProc3, &thrParams4, 0, NULL);
HANDLE handleEmployee4 = CreateThread(NULL, 0, ThrEmployeeProc4, &thrParams4, 0, NULL);
HANDLE handleEmployee5 = CreateThread(NULL, 0, ThrEmployeeProc5, &thrParams4, 0, NULL);
//关闭线程句柄
CloseHandle(handleEmployee1);
CloseHandle(handleEmployee2);
CloseHandle(handleEmployee3);
CloseHandle(handleEmployee4);
CloseHandle(handleEmployee5);
}

case WM_DESTROY:
//关闭信号量
CloseHandle(g_hSem);
PostQuitMessage(0);
break;

来看一下线程函数吧.

DWORD WINAPI ThrEmployeeProc1(LPVOID lp)
{
PPARAMS param4 = static_cast<PPARAMS>(lp);
//等待这个信号量  永远阻塞 如果信号量的  当前资源计数 大于0 就触发 反悔
WaitForSingleObject(g_hSem,INFINITE);  //当他返回的时候 当前资源计数会 减1
//休眠2秒
Sleep(2000);
//获取当前毫秒数
DWORD dwCurTime = GetTickCount();
//获得DC
HDC hdc = GetDC(param4->hwnd);
//显示文本
BOOL bF = TextOut(hdc, 0, (g_iLine4++)*param4->cyChar, _T("员工线程1正在使用公司上网"), lstrlen(_T("员工线程1正在使用公司上网")));
//释放dc 
ReleaseDC(param4->hwnd,hdc);
//循环10秒退出
while (true)
{
if ((GetTickCount() - dwCurTime) > 1000 * 10)
{
HDC hdc = GetDC(param4->hwnd);
SetTextColor(hdc, RGB(255, 0, 0));
TextOut(hdc, 0, (g_iLine4++)*param4->cyChar, _T("员工线程1已经没有使用公司上网"), lstrlen(_T("员工线程1已经没有使用公司上网")));
ReleaseDC(param4->hwnd, hdc);
break;
}
Sleep(1000);
}
//释放信号量 信号量句柄 穿进去 并且
// 1代表加1 当前资源计数器+1  可以+2 +3 但是现在加1最合适
// 最后一个参数是反回上一次资源计数器的数量  大部分情况下 不需要这个东西
ReleaseSemaphore(g_hSem,1,NULL);
return 0;
}

效果:

我们发现 这个上网的数量,是通过信号量被控制住了,每次最多

可以有两个员工可以上网。

有不懂的连续我qq:2438746951

交流群:140066160

源代码地址:http://down.51cto.com/data/2329794

时间: 2024-12-17 00:50:39

VC++线程同步(五) 信号量使用例子的相关文章

VC++线程同步(四) 事件使用例子

事件(Event)同步对象 (内核级别)事件内核对象包含: 1 一个使用计数器 2 一个表示事件是否是自动重置还是手动重置的布尔值 3 一个表示事件有没有被触发的布尔值 4 当触发为true时,等待该事件的线程变为可调度状态 5 事件的触发表示一个操作已经完成 作用: 通知其他线程,我已经完成读写操作了,轮到你们来做了. 他分为两种类型: 1是手动重置事件,也就是要进行手动的触发和非触发状态的切换. 2是自动重置事件,这种情况下只需要设置触发事件,不用管什么时候切换触发状态. 尽量使用手动重置方

VC++线程同步(三) 临界区使用例子

临界区(Crtical Section)同步对象 用户模式下的同步对象 Win32中,最容易使用的一个同步机制就是(关键段)Critical Section, 某些共享资源具有互斥性,也就是它要求被互斥地使用,他也是用于资源的互斥, 在大部分情况下,使用临界区替换Mutex(Mutex是内核模式下的同步对象). 局限性:他只能用于同步单个进程中的线程. 在任何同步机制当中,无论是哪个操作系统下,都不要 长时间的锁住资源,如果一直锁定资源,就会一致阻止其他线程的执行, 使整个程序,处于完全停止的状

线程同步之信号量

线程同步之信号量 Semaphore 信号量. 它维护一个计数,当值大于0时,信号量对象处于已传信状态.通常用数值表示可用资源的个数. WaitForSingleObject()令信号量减一:ReleaseSemaphore()令信号量加一. 线程同步之信号量,布布扣,bubuko.com

VC++ 线程同步 总结

注:所谓同步,并不是多个线程一起同时执行,而是他们协同步调,按预定的先后次序执行. 与线程相关的基本函数包括:CreateThread:创建线程CloseHandle:关闭线程句柄.注意,这只会使指定的线程句柄无效(减少该句柄的引用计数),启动句柄的检查操作,如果一个对象所关联的最后一个句柄被关闭了,那么这个对象会从系统中被删除.关闭句柄不会终止相关的线程. 线程是如何运行的呢?这又与你的CPU有关系了,如果你是一个单核CPU,那么系统会采用时间片轮询的方式运行每个线程:如果你是多核CPU,那么

线程同步wait notify小例子

<strong>线程同步小例子:开启两个线程实现拿鸡蛋 放鸡蛋交叉进行</strong> </pre><pre code_snippet_id="574008" snippet_file_name="blog_20150107_1_8603573" name="code" class="java">public class Dofunction { private int num

VC++线程同步(二) Mutex互斥量的例子

同步对象使用实例 Win32窗口的建立: 我们将要学习的使用,分别是:互斥量,临界区,事件,信号量.所以我们需要一个窗口,呈现四种四种同步对象状态. 首先创建一个Win32项目,不要选空项目; 我们需要四个小窗口,先找到注册主窗口的代码. ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW

Python 线程同步锁, 信号量

同步锁 import time, threading def addNum(): global num num -= 1 num = 100 thread_list = [] for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: t.join() print('final num:', num) 运行结果: final num:

c++线程同步之信号量

// MutexExDlg.h : 头文件 // #pragma once // CMutexExDlg 对话框 class CMutexExDlg : public CDialogEx { // 构造 public: CMutexExDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_MUTEXEX_DIALOG }; protected: virtual void DoDataExchange(CDataExchang

4线程同步:信号量

1 信号量 信号量可以有n把锁. 依赖的头文件 #include <semaphore.h> 函数声明 sem_t 表示信号量 int sem_init(sem_t *sem, int pshared,unsigned int value); 名称: sem_init 功能: initialize an unnamed semaphore,初始化信号量sem_t,初始化的时候可以指定信号量的初始值,以及是否可以在多进程间共享. 头文件: #include <semaphore.h>