信号量相当于一个计数器,记录一个共享资源被访问线程的个数;好比有两个或者更多个办事窗口,他们都做同一件事;假设有5个窗口,五个窗口都没人访问的时候计数器为5;有一个窗口被占用计数器减1,为4;全部被占用则计数器为0;这时候其他人想要访问就必须等待占用结束后计数器加1;
HANDLE WINAPI CreateSemaphore(
__in LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
__in LONG lInitialCount,//初始化计数
__in LONG lMaximumCount,//最大计数
__in LPCTSTR lpName //名称
);
BOOL WINAPI ReleaseSemaphore(
__in HANDLE hSemaphore, //信号量句柄
__in LONG lReleaseCount,//释放个数
__out LPLONG lpPreviousCount//
);
实例:
写一个可多读多写的队列
#pragma once
#include <stdlib.h>
#include <Windows.h>
#define G_MAX 10 // 信号量最多同时访问线程数量
#define MAXTHREAD 20 //读写线程个数
//模板不支持将声明与实现分两个文件实现; 会出错 link 2019 找不到实现文件
template <class T>
class CMyDeque
{
public:
CMyDeque();
~CMyDeque();
void PushValue(const T &element);
T PopValue();
private:
HANDLE g_Samephore_R; // 读信号量
HANDLE g_Samephore_W; // 写信号量
//HANDLE h_Read[MAXTHREAD];
//HANDLE h_Write[MAXTHREAD];
int nDequeLen; // 队列长度 默认为1024
int nBack; //队尾
T * m_data;
};
template <class T>
CMyDeque<T>::CMyDeque()
{
nDequeLen = 1024;
nBack = 0;
m_data = new T[1024];
g_Samephore_R = CreateSemaphore(NULL, G_MAX, G_MAX, L"ReadSem");
g_Samephore_W = CreateSemaphore(NULL, 1, 1, L"WriteSem");
}
template <class T>
CMyDeque<T>::~CMyDeque()
{
/*
for (int i = 0; i < MAXTHREAD; i++)
{
CloseHandle(h_Read[i]);
CloseHandle(h_Write[i]);
}
*/
CloseHandle(g_Samephore_W);
CloseHandle(g_Samephore_R);
}
template <class T>
void CMyDeque<T>::PushValue(const T &element)
{
if ((nBack+1) % nDequeLen == 0)
{
T *temp = m_data;
nDequeLen = nDequeLen * 2;
m_data = new T[nDequeLen];
for (int i = 0; i < nBack; i++)
{
m_data[i] = temp[i];
}
}
WaitForSingleObject(g_Samephore_W, INFINITE);
m_data[nBack] = element;
nBack++;
ReleaseSemaphore(g_Samephore_W, 1, NULL);
}
template <class T>
T CMyDeque<T>::PopValue()
{
WaitForSingleObject(g_Samephore_R, INFINITE);
WaitForSingleObject(g_Samephore_W, INFINITE);
T result = m_data[nBack-1];
ReleaseSemaphore(g_Samephore_W, 1, NULL);
ReleaseSemaphore(g_Samephore_R, 1, NULL);
return result;
}
// MutiRWDeque.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "CMutiWRDeque.h"
#include <thread>
#include <mutex>
CMyDeque<int> mydeque;
static int i = 0;
std::mutex mutexlock;
void read()
{
while (i<100)
{
cout << "线程" << GetCurrentThreadId() << "读出数据" << mydeque.PopValue() << endl;
Sleep(1000);
}
}
void write()
{
while (i<100)
{
mutexlock.lock();
i++;
mydeque.PushValue(i);
cout << "线程" << GetCurrentThreadId() << "写入数据" << i << endl;
mutexlock.unlock();
Sleep(400);
}
}
int main()
{
thread t1(write);
thread t2(write);
thread t3(write);
thread t4(write);
thread t5(write);
thread t6(write);
thread t7(read);
thread t8(read);
thread t9(read);
thread t10(read);
thread t11(read);
thread t12(read);
while (1)
{
};
system("pause");
return 0;
}