信号量也是线程间同步常用的手段之一。举个例子,比如我们要去餐馆吃饭,这家餐馆一共有4个位置,我们一共是6个人。那么就会4个人先去吃饭,等他们吃完了,剩下的2个人再去吃饭,如果再来人则需要判断是否有空位置,如果有直接坐下吃饭,如果没有则需要等待。
这里的每一个顾客就相当于一个线程,而通知你排队叫号进餐的那个服务员就是我们的信号量。信号量可以有效的保证我们多个线程并发执行。
对于信号量,我们经常使用的函数如下:
关于该函数的介绍可参照:线程的互斥和同步(3)- Windows的互斥锁
下面是关于信号量的简单示例:
这里同样使用的 CThread ,头文件:
#include "CThread.h"
class SemaphoreThread : public CThread
{
public:
void run(void) override;
// 创建信号量
static void createSemaphore(int number);
};
源文件:
#include <iostream>
#include <atomic>
HANDLE g_semphore;
std::atomic<int> number(0);
void SemaphoreThread::run(void)
{
if (::WaitForSingleObject(g_semphore, INFINITE) == WAIT_OBJECT_0)
{
number++;
std::cout << "Custom " << ::GetCurrentThreadId() << ", Sit Down!" \
<< " Your are " << number << "th Cunstom." << std::endl;
::Sleep(300);
::ReleaseSemaphore(g_semphore, 1, nullptr);
}
else
std::cout << "Error!" << std::endl;
}
void SemaphoreThread::createSemaphore(int number)
{
// 创建信号量
g_semphore = ::CreateSemaphore(nullptr, number, number, nullptr);
}
调用部分:
int main(int argc, char** argv)
{
// 四个资源 - 餐馆4个座位
SemaphoreThread::createSemaphore(4);
// 创建6个线程,6个客人排队等待4个座位
SemaphoreThread thread[6];
for (int i = 0; i < 6; ++i)
thread[i].start();
for (int i = 0; i < 6; ++i)
thread[i].wait();
system("pause");
return 0;
}
这个示例中,模拟6个客人排队等待4个座位。
执行结果:
Custom 8932, Sit Down! Your are 1th Cunstom.
Custom 9760, Sit Down! Your are 2th Cunstom.
Custom 7836, Sit Down! Your are 3th Cunstom.
Custom 13736, Sit Down! Your are 4th Cunstom.
Custom 20900, Sit Down! Your are 5th Cunstom.
Custom 9308, Sit Down! Your are 6th Cunstom.