`

经典线程同步 信号量Semaphore

 
阅读更多

 

信号量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()就可以完成清理与销毁了。

 

信号量的使用规则:

1. 如果当前资源计数大于0,那么信号量处于触发状态;

2. 如果当前资源计数等于0,那么信号量处于未触发状态;

3. 系统绝对不会让当前资源计数变为负数;

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

 

        在使用信号量的时候,不要把信号量对象的使用计数和它的当前资源计数混为一谈。

因为在创建该信号量句柄时,这个内核对象的使用计数为1,而当前资源计数我们可以自己设定。 

0表示当前有0个资源可用,最大资源个数可以是计算机能表示的最大32位数。

 

        为了获得对被保护资源的访问权,线程要调用一个等待函数并传入信号量的句柄。在内部,等待函数会检查信号量的当前资源计数,如果它的值大于0(信号量处于触发状态),那么函数会把计数器减1 并让调用线程继续运行。信号量最大的优势在于他们会以原子方式来执行这些测试和设置操作,也就是说,当我们向信号量请求一个资源的时候,操作系统会检查资源是否可用,并将可用资源的数量递减,整个过程不会被别的线程打断。

        如果等待函数发现信号量的当前资源计数为0(信号量处于未触发状态),那么系统会让调用线程进入等待状态。

 

        在经典多线程问题中设置一个信号量和一个关键段。用信号量处理主线程与子线程的同步,用关键段来处理各子线程间的互斥。

实例代码如下:

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

using namespace std;

const int NUM = 10;
int count;
HANDLE semaphore;
CRITICAL_SECTION sc;

unsigned int __stdcall funcTh(PVOID pm) {
	int a = *((int *) pm);
	ReleaseSemaphore(semaphore, 1, NULL);
	EnterCriticalSection(&sc);
	count++;
	cout << "第" << a <<  "个线程" << "     " << "全局资源值为" << count << endl;
	LeaveCriticalSection(&sc);
	return 0;
}

int main() {

	HANDLE handles[NUM];

	semaphore = CreateSemaphore(NULL, 0, 5, NULL);
	InitializeCriticalSection(&sc);

	int i;
	for(i=0; i<NUM; i++) {
		handles[i] = (HANDLE) _beginthreadex(NULL, 0, funcTh, &i, 0, NULL);
		WaitForSingleObject(semaphore, INFINITE);
	}
	WaitForMultipleObjects(NUM, handles, true, INFINITE);

	DeleteCriticalSection(&sc);
	CloseHandle(semaphore);

	getchar();
	return 0;
}

 

运行结果如下:


 

 

 

 

  • 大小: 16.4 KB
分享到:
评论

相关推荐

    使用信号量(Semaphore)实现线程的同步

    使用信号量(Semaphore)实现线程的同步

    多线程代码 经典线程同步互斥问题 生产者消费者问题

    a: 创建一个线程 b: 创建多个线程 c: 多线程访问同一资源 d: 经典线程同步互斥问题 e: 使用关键段解决子线程互斥问题 f: 利用事件实现线程同步问题 ...I: 信号量 semaphore 解决线程同步问题

    NET多线程同步方法详解

    1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent)2) 线程池 除了以上的这些对象之外实现线程同步的还可以使用Thread.Join方法。这种方法比较简单,当你在第一个线程运行时想等待第二个...

    多线程编程——信号量使用(Jack_semaphore_test.rar)

    多线程编程:信号量使用。 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可执行...

    linux之线程同步一.doc

    2. 信号量(Semaphore):信号量是一种用于控制并发访问的同步机制,它通常用于限制同时访问共享资源的线程数量。信号量可以是一个非负整数,用于表示可用的资源数量。当一个线程请求资源时,如果可用资源数量大于零...

    linux之线程同步的概要介绍与分析

    2. **信号量(Semaphore)**:信号量是一种更为灵活的同步工具,不仅可以实现互斥,还能控制资源的数量。它维护一个整型计数器,并提供两个原子操作:`wait()`(减计数)和`signal()`(加计数)。当计数为非正时,`...

    C#信号量,用于多线程

    Semaphore,是负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。也是操作系统中用于控制进程同步互斥的量。

    详解java多线程的同步控制

    目录线程安全 Thread Safety重入锁 ReentrantLock读写锁 ReadWriteLock倒计数器 CountDownLatch循环栅栏 CyclicBarrier信号量 Semaphore 线程安全 Thread Safety JMM JMM(Java Memory Model)是一种基于计算机内存...

    深入了解c# 信号量和互斥体

    在.net 下通过Semaphore类来实现信号量同步。 Semaphore类限制可同时访问某一资源或资源池的线程数。WaitOne method, which is inherited from the WaitHandle class, and release the semaphore by calling the ...

    C#实现多线程的同步方法实例分析

    本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再赘述了。直接接入 主题,在多线程开发的应用...1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent) 2) 线程池 除了以上

    python多线程DAY04.txt

    2. 信号量 Semaphore() acquire() 删除 release() 增加 get_value() 获取 3. 同步互斥机制 : 解决了多个进程或者线程对共享资源的争夺 Event e.set e.clear e.wait Lock lock.acquire() lock.release() 4...

    C#实现多线程的同步方法详解

    本文主要描述在C#中线程同步的方法。线程的基本概念网上资料也很多就不再...系统内核对象1)互斥(Mutex),信号量(Semaphore),事件(AutoResetEvent/ManualResetEvent)2)线程池除了以上的这些对象之外实现线程同步的还可

    dispatch_semaphore

    //信号量用途1://两个资源,三个线程执行;设定信号量值为2,先执行两个线程,等执行完一个,才会继续执行下一个,保证同一时间执行的线程不超过两个,保证线程的最大并发数 ...//信号量用途3:同步不同线程的操作

    Simple-Windows-Posix-Semaphore:一个简单的窗口 POSIX 信号量库

    POSIX 信号量允许进程和线程同步它们的动作。 信号量是一个整数,其值决不允​​许低于零。 可以对信号量执行两种操作:将信号量值加一 [ sem_post ]; 并将信号量值减一 [ sem_wait ]。 如果信号量的值当前为零,则...

    控制线程同步的几个内核对象

    由于线程采用并发运行机制,因此当进程运行时,其各线程的运行进度可能不一致,所以需要对各个线程的运行过程进行同步。其中常用的控制线程同步的机制有下面几种:互斥对象,事件对象,信号量,临界区等等。

    c#线程同步使用详解示例

    在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。对于 Windows 应用程序,...线程同步有:临界区、互斥区、事件、信号量四种方式临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、

    java线程源码-Dinning-Philosopher-Problem:用线程和信号量概念的Dinning哲学家问题解决方案Java源代码

    java线程源码带有信号量和线程的Dinning哲学家问题。 信号量是整数变量,用于通过使用两个原子操作(用于过程同步的wait和signal)来解决关键部分问题。 等待和信号的定义如下: Wait-等待操作减小其参数s的值(如果...

    《Visual C++范例大全》随书光盘 第十一章

    实例268——使用信号量(Semaphore)实现线程的同步 实例269——使用多线程进行文件搜索 实例270——获取当前系统的所有进程 实例271——实现应用程序在系统中只能运行一个实例 实例272——获取所有打开窗口...

    个人总结的深入java多线程开发

    6)信号量Semaphore 31 7)ReentrantLock可重入的互斥锁定 Lock 32 8)阻塞队列BlockingQueue 34 9)已完成任务队列CompletionService 36 10)计时器CountDownLatch 37 11)周期性同步工具CyclicBarrier 38 12)异步计算的...

    dispatch_semaphore two

    ios开发GCD的dispatch_semaphore:1、常用函数及作用 2、信号量的用途:1》同步不同线程 2》当做锁来使用:3》控制同时执行的线程数:

Global site tag (gtag.js) - Google Analytics