C++ 信号量 多线程同步互斥

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

PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。 

 P操作 申请资源:  

(1)S减1;  

(2)若S减1后仍大于等于零,则进程继续执行;  
(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。  

V操作 释放资源:  

(1)S加1;  

(2)若相加结果大于零,则进程继续执行;  
(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。   
信号量包含的几个操作原语:  

CreateSemaphore() 创建一个信号量  

OpenSemaphore() 打开一个信号量  

ReleaseSemaphore() 释放信号量 

WaitForSingleObject() 等待信号量  

#include <Windows.h>
#include <stdio.h>

HANDLE hSemaphore = NULL;
const char* strSemaphoreName = "MySemaphore";
const int threads_num = 50;
HANDLE Threads[threads_num];
bool bExitThreads = FALSE;

void WINAPI ThreadFun(void* param)
{
    printf("线程 %u 开始运行\n", GetCurrentThreadId());
    WaitForSingleObject(hSemaphore,INFINITE);
    printf("线程 %u 获得信号量,继续运行\n", GetCurrentThreadId());
    while(!bExitThreads)
    {
            Sleep(10);
    }
    long dwSem = 0;
    if (!ReleaseSemaphore(hSemaphore, 1, &dwSem))
    {
        if (0 == GetLastError())
        {
            printf("当前可用资源数:20\n");
            return;
        }
    }
    
    printf("当前可用资源数:%u\n", dwSem);
}

void creatThreads()
{
    DWORD dwThreadID = 0;
    for (int i =0; i < threads_num; ++i)
    {
        Threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFun, NULL, 0, &dwThreadID);
        if (!Threads[i])
        {
            printf("创建线程失败!\n");
        }
        printf("线程 %u 创建成功\n", dwThreadID);
    }
}

void  main()
{
    hSemaphore = CreateSemaphoreA(NULL, 0, 20, strSemaphoreName);
    if(NULL == (hSemaphore = OpenSemaphoreA(SEMAPHORE_MODIFY_STATE , FALSE, strSemaphoreName)))
    {
        printf("打开信号量对象失败 , 错误ID:%u\n", GetLastError());
        return;
    }

    creatThreads();
    bExitThreads = true;
    WaitForMultipleObjects(threads_num, Threads, TRUE, INFINITE);

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值