信号量

信号量对线程的同步方式与前面几种方法不同,信号量允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数。每增加一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能再允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。 
CreateSemaphore() 创建一个信号量 
OpenSemaphore() 打开一个信号量 
WaitForSingleObject() 等待信号量

ReleaseSemaphore() 释放信号量 

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE g_hSemaphore = NULL;
int tickets = 100;

DWORD WINAPI FUNCPROC1(LPVOID) {
	while (TRUE) {
		WaitForSingleObject(g_hSemaphore, INFINITE);
		if (tickets > 0) {
			cout << "thread1 sell ticket: "<<tickets-- << endl;
			ReleaseSemaphore(g_hSemaphore, 1, NULL);
		}
		else {
			ReleaseSemaphore(g_hSemaphore, 1, NULL);
			break;
		}
	}

	return 0;
}

DWORD WINAPI FUNCPROC2(LPVOID) {
	while (TRUE) {
		WaitForSingleObject(g_hSemaphore, INFINITE);
		if (tickets > 0) {
			cout << "thread2 sell ticket: " << tickets-- << endl;
			ReleaseSemaphore(g_hSemaphore, 1, NULL);
		}
		else {
			ReleaseSemaphore(g_hSemaphore, 1, NULL);
			break;
		}
	}

	return 0;
}

int main() 
{
	//设置信号量的初始计数和最大计数都为1
	g_hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
	HANDLE hThread1 = CreateThread(NULL, 0, FUNCPROC1, NULL, 0, NULL);
	HANDLE hThread2 = CreateThread(NULL, 0, FUNCPROC2, NULL, 0, NULL);

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);

	CloseHandle(hThread1);
	CloseHandle(hThread2);
	CloseHandle(g_hSemaphore);

	return 0;
}

总结:
1、互斥量、事件、信号量都是内核对象,可用于进程间的线程同步;而临界区是进程内对象,只能用于进程内的线程同步。互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多,如果只为了在进程内部使用的话,临界区会带来速度上的优势并能够减少资源占用量。因为互斥量是跨进程的,互斥量一旦被创建,就可以通过名字打开它。 


2、事件和其他几个同步方法的不同在于事件的主要作用不是保护共享的资源,而是用于等待某个事件和在特定的事件发生时发送信号,以协调线程之间的动作。
 
3、信号量与其他同步方法的区别在于它允许一个以上的线程同时访问共享资源,而其他线程同步方法都保证同时只能有一个线程访问共享的资源。信号量主要是用于资源计数,能够控制有限用户使用资源。通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号量对象可以说是一种资源计数器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值