`
jishublog
  • 浏览: 868419 次
文章分类
社区版块
存档分类
最新评论

Windows进程同步之信号量内核对象(Semaphore)

 
阅读更多

信号量内核对象主要包括三个部分:使用计数最大资源计数当前资源计数

  • 使用计数:和其他内核对象一样,用来标识使用该事件对象的不同线程个数;
  • 最大资源计数:表示信号量控制的最大资源的数目;
  • 当前资源计数:表示信号量当前可用的资源数目;

信号量使用规则如下:

  1. 如果当前资源计数大于0,信号量处于触发状态;
  2. 如果当前资源计数等于0,那么信号量处于未触发状态;
  3. 系统绝不会使当前资源计数变为负数;
  4. 系统绝对不会使当前资源计数超过最大资源计数;

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

下面是使用信号量内核对象的所要使用的函数接口:

1CreateSemaphore()

HANDLE WINAPI CreateSemaphore(
  _In_opt_  LPSECURITY_ATTRIBUTES lpEventAttributes,
  _In_      LONG lInitialCount,
  _In_      LONG lMaximumCount,
  _In_opt_  LPCTSTR lpName
);

lpEventAttributes:事件对象的安全属性,一般置为NULL

lInitialCount:表示一开始可以使用的资源数目,即当前资源计数;

lMaximumCount:信号量对象可以处理的最大资源数量;

lpName:创建有名的信号量对象,用于进程间的共享;

如果该信号量对象已经存在,那么CreateSemaphore会返回该内核对象的句柄,并通过系统返回错误ERROR_ALREADY_EXISTS,通过GetLastError()获得。

2OpenSemaphore()

HANDLE WINAPI OpenSemaphore(
  _In_  DWORD dwDesiredAccess,
  _In_  BOOL bInheritHandle,
  _In_  LPCTSTR lpName
);

dwDesiredAccess:指定想要的访问权限,SEMAPHORE_ALL_ACCESS请求对事件对象的完全访问,SEMAPHORE_MODIFY_STATE修改状态权限,使用ReleaseSemaphore函数需要该权限;

bInheritHandle:是否希望子进程继承信号量对象的句柄,一般设置为false

lpName:要打开的信号量对象的名称;

其他进程中的线程可以通过OpenSemaphoreCreateSemaphore访问已经存在的信号量内核对象。和其他内核对象的访问一样。

3WaitForSingleObject()

DWORD WINAPI WaitForSingleObject(
  _In_  HANDLE hHandle,
  _In_  DWORD dwMilliseconds
);

hHandle:指向内核对象的句柄;

dwMilliseconds:线程最大等待多长时间,直到该对象被触发。经常使用INFINITE,表示阻塞等待。

WaitForSingleObject被称呼为等待函数,是等待内核对象被触发通用的等待函数,被用在所有的内核对象触发等待中。等待函数会检查信号量的当前资源使用计数,如果大于0,表示信号量处于触发状态,那么等待函数会把资源使用计数器减1,并让调用线程继续执行。信号量的最大优势就是在于以原子的方式来执行这些测试和设置操作。如果等于0,表示信号量处于未触发状态,那么系统会让调用线程进入等待状态,直到被唤醒(当前资源计数大于0)。

4ReleaseSemaphore()

BOOL WINAPI ReleaseSemaphore(
  _In_       HANDLE hSemaphore,
  _In_       LONG lReleaseCount,
  _Out_opt_  LPLONG lpPreviousCount
);

hSemaphore:信号量内核对象的句柄;

lReleaseCount:释放自己使用的资源数目,加到信号量的当前资源计数上,通常会传1,当然是根据线程使用的资源数目而定。

lpPreviousCount:返回当前资源计数的原始值,应用程序很少会用到这个值,所以一般置为NULL

当一个线程使用完信号量对象控制的有限资源后,应该调用ReleaseSemaphore,释放使用的资源,使信号量对象的当前资源计数得到恢复。

5CloseHandle()

BOOL WINAPI CloseHandle(
  _In_  HANDLE hObject
);

hObject:指向内核对象的句柄

和其他内核对象一样,无论以什么方式创建内核对象,我们都必须通过调用CloseHandle向系统表明结束使用内核对象。如果传入的句柄有效,系统将获得内核对象数据结构的地址,并将结构中的使用计数减1,如果使用计数0,就会将内核对象销毁,从内存空间中擦除。

下面是信号量部分代码测试:

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

using namespace  std;

void semaphoreTest(void *ptr)
{
    int flag = *(int *)ptr;

    HANDLE semaphore = CreateSemaphore(NULL, 2, 2, (LPCWSTR)"streamSemaphore");

    WaitForSingleObject(semaphore, INFINITE);

    ofstream fileStream("c:/test.txt", ios_base::app);

    for (int i = 0; i < 5; ++i)
    {
        Sleep(1000);
        fileStream<<flag;
        fileStream<<' '<<flush;

        //cout<<flag<<' ';
    }

    fileStream.close();

    ReleaseSemaphore(semaphore, 1, NULL);
    CloseHandle(semaphore);
}


int main()
{
    int flag[] = {1, 2, 3};

    for (int i = 0; i < 3; ++i)
    {
        _beginthread(semaphoreTest, 0, &flag[i]);
    }
    
    Sleep(INFINITE);
        
}

代码在主线程中依次启动三个线程,每个线程对同一个文件进行写操作,但同一时间最多只能有两个线程对这个文件进程操作,所以执行结果如下:

2 1 2 1 2 1 2 1 2 1 3 3 3 3 3


Jun 19, 2013 AM 01:29 @dorm

分享到:
评论

相关推荐

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

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

    信号量(Semaphore)

    信号量(Semaphore)哲学家进餐问题(the dining philosophers problem)---------------------------程序

    java并发之Semaphore信号量.md

    Semaphore是计数信号量。Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法。然而,其实并没有...

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

    介绍临界资源的访问机制,有Semaphore,signal,mutex等

    ucosIII信号量多值信号量二值信号量互斥信号量

    信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间同步或临界资源的互斥访问 (临界资源指同一时刻只能有有限个访问),常用于协助一组相互竞争的任务来访问临界资源。运行机制可以理解为:信号量是...

    JAVA多线程--信号量(Semaphore)_.docx

    JAVA多线程--信号量(Semaphore)_.docx

    L16 进程同步与信号量

    每一个进程有一段程序,执行不是顺序执行,有些地方需要等待其他进程发发送信号才能执行。 进程同步: 需要让进程走走停停来保证进程合理有序称为进程同步。 但从依靠counter进行语义判断不足以判断到底来了几个...

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

    信号量(Semaphore)是由内核对象维护的int变量,当信号量为0时,在信号量上等待的线程会堵塞,信号量大于0时,就解除堵塞。当在一个信号量上等待的线程解除堵塞时,内核自动会将信号量的计数减1。在.net 下通过...

    信号量Semaphore了解过吗?

    难堪的一次面试: 信号量Semaphore了解过吗?没有

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

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

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

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

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

    主要介绍了JAVA 多线程之信号量(Semaphore)实例详解的相关资料,需要的朋友可以参考下

    C++中Semaphore内核对象用法实例

    本文实例讲述了C++中Semaphore内核对象的用法,分享给大家供大家参考。具体方法如下: 代码如下:// Semaphore.cpp : 定义控制台应用程序的入口点。  //    #include “stdafx.h”  #include &lt;Windows&gt;  #...

    Java信号量Semaphore

    Semaphore  Semaphore分为单值和多值两种,前者只能被一个线程获得,...单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场

    async-semaphore:基于Java并发信号量的计数信号量

    异步信号量 基于 Java 的并发信号量的计数信号量。 安装 通过 npm 安装模块: npm install async-semaphore 快速示例 // fairness false var Semaphore = require ( 'async-semaphore' ) ; var semaphore = new ...

    Threadx 释放信号量_tx_semaphore_put

    释放信号量_tx_semaphore_put 1,如果tx_semaphore_suspension_list挂起队列为空,那么直接把tx_semaphore_count计数器加一 2,如果tx_semaphore_suspension_list挂起队列不为空,那么tx_semaphore_suspension_list...

    python线程信号量semaphore使用解析

    这篇文章主要介绍了python线程信号量semaphore使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.semaphore信号量原理 多线程同时运行,能提高程序的...

    vxworks多任务(task和semaphore信号量及事件)例程.zip

    资源包含了vxworks多任务(task和semaphore信号量及事件)的相关编程例子,通过创建多任务的简单例子,帮助大家了解taskSpawn函数、信号量semaphore、以及事件event的使用方法。

    semaphore的使用.pdf

    关于Android变成中的信号量semaphore,在使用过程中我们往往搞不清楚其信号量的申请和使用。这里主要针对信号量初始值为零的情况做介绍,其他情况不做讨论。初始值为零的情况较少使用,部分代码中的这个情况往往让...

Global site tag (gtag.js) - Google Analytics