`

经典线程同步 信号量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
分享到:
评论

相关推荐

    c++多线程同步——信号量

    信号量(Semaphore)是实现多线程同步的一种有效工具,常用于控制对共享资源的访问。在这个名为"Mthread11"的MFC工程中,我们可以看到如何在C++环境中应用信号量来解决多线程间的同步问题。 首先,我们需要理解什么...

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

    信号量(Semaphore)是...信号量是解决线程同步问题的一种高效工具,通过合理的信号量控制,可以有效地避免死锁、饥饿等问题,提高系统资源的利用率。理解并正确使用信号量,对于编写高效、稳定的多线程程序至关重要。

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

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

    使用信号量实现线程同步

    信号量(Semaphore)是实现线程同步的一种有效工具,它源于早期的计算机操作系统理论,由荷兰计算机科学家Dijkstra提出。在Windows系统中,信号量作为内核对象被广泛使用,可以用来控制对共享资源的访问。 信号量的...

    Visual C++信号量线程同步的简单实例工程

    本实例工程“Visual C++信号量线程同步的简单实例工程”聚焦于如何通过信号量(Semaphore)实现线程间的协调与同步,以确保资源的有效管理和避免竞态条件。 首先,我们需要理解什么是信号量。信号量是一种同步原语...

    qt5多线程,信号量,互斥量,等待条件

    本文将详细探讨如何利用QT5的线程机制,以及信号量(Semaphore)、互斥量(Mutex)和等待条件(Condition Variable)等同步原语,来构建一个高效的生产者-消费者模型。 首先,我们要理解线程的基本概念。线程是程序...

    信号量机制实现线程同步

    4. **哲学家就餐问题**:这是一个经典的多线程同步问题,通过信号量解决。五个哲学家围坐在一张圆桌旁,每人面前有一根筷子。当一个哲学家想吃饭时,他需要左右两边的筷子。如果同时有两个哲学家去拿筷子,会导致...

    JAVA 多线程之信号量(Semaphore)实例详解

    在Java多线程编程中,信号量Semaphore是一种非常重要的同步工具,用于控制对公共资源的访问。Semaphore类位于`java.util.concurrent`包下,它允许我们限制同时访问特定资源的线程数量。 ### Semaphore简介 信号量...

    windowsC++多线程加锁信号量共享内存

    在这个场景下,"windowsC++多线程加锁信号量共享内存"就是我们要探讨的核心主题。 首先,让我们了解什么是多线程。多线程是指一个进程中可以同时执行多个独立的执行流,每个流被称为一个线程。在C++中,可以通过`...

    信号量同步等待机制 semaphore wait-and-signal

    ### 信号量同步等待机制(Semaphore Wait-and-Signal) #### 一、引言 在多线程编程中,临界资源的访问管理是一项至关重要的任务。为了确保数据的一致性和程序的正确执行,必须采取有效的机制来防止多个线程同时...

    semaphore控制多线程循序执行

    Semaphore(信号量)是一种经典的同步机制,它源自于荷兰计算机科学家Edsger W. Dijkstra提出的银行家算法。本示例中,我们将深入探讨如何使用Semaphore来控制多线程的循序执行。 Semaphore是一种计数信号量,它...

    易语言多线程控制:信号量控制线程数量

    信号量(Semaphore)是一种经典的同步机制,用于控制对共享资源的访问。在易语言中,我们可以利用其提供的信号量API来实现线程间的同步与互斥。信号量值可以用来表示资源的可用数量,当线程试图获取一个资源时,如果...

    vc++ multithread多线程教程---线程通信--利用事件对象,线程同步--使用信号量,线程同步--使用互斥量,线程同步--使用临界区

    本教程将深入探讨四种常见的线程同步机制:事件对象、信号量、互斥量以及临界区,帮助开发者理解和掌握如何在VC++中安全地实现多线程通信。 一、事件对象 事件对象是Windows API中用于线程间通信的一种同步机制。它...

    VisualC++线程同步技术剖析临界区,时间,信号量,互斥量[定义].pdf

    Visual C++ 线程同步技术剖析:临界区、事件、信号量、互斥量 多线程同步技术是计算机软件开发的重要技术, Visual C++ 提供了多种线程同步技术来确保线程之间的安全交互。本文对 Visual C++ 中的多线程同步技术...

    2.线程间同步和通信之信号量(静态)

    本教程将深入探讨如何使用信号量进行线程间的同步和通信,特别是在STM32平台上的实践应用。 信号量,作为一种资源管理机制,用于控制对共享资源的访问。在多线程环境中,当多个线程尝试同时访问有限资源时,信号量...

    python线程信号量semaphore使用解析

    Python中的线程信号量(Semaphore)是多线程编程中的一种同步机制,它主要用于控制对共享资源的访问,以防止过多的线程同时访问而导致资源竞争。信号量维护了一个内部计数器,该计数器表示可以并发访问的资源数量。...

    VC线程信号量的使用举例

    在深入理解了信号量的工作原理后,开发者可以灵活运用它来解决更复杂的线程同步问题,如生产者消费者模型、读写锁等。同时,VC++还提供了其他同步对象,如互斥量(Mutex)、事件(Event)和临界区(Critical Section...

    线程同步的四种方式

    在C++17中,可以使用`std::counting_semaphore`和`std::binary_semaphore`来实现信号量。 4. **临界区(Critical Section)** 临界区是代码段,其中包含对共享资源的访问。任何时刻,只有一个线程可以处于临界区。...

    线程同步(信号量,互斥,条件变量)

    **信号量(Semaphore)**是另一种线程同步工具,它允许有限数量的线程同时访问资源。信号量可以分为二进制信号量(类似于互斥量,只能为0或1,表示资源是否可用)和计数信号量(可设置任意非负整数值,表示资源的...

    基于信号量的Linux多线程同步研究.pdf

    ### 基于信号量的Linux多线程同步研究 #### 摘要与背景 在多线程编程中,确保各个线程之间的同步是非常重要的,以避免出现资源竞争和死锁等问题。信号量是一种常用的同步机制,它可以有效管理线程间的资源共享。...

Global site tag (gtag.js) - Google Analytics