练习API
CreateSemaphore
CreateEvent
ReleaseSemap
WaitForSingleObject
CloseHandle
InitializeCriticalSection
EnterCriticalSection
LeaveCriticalSection
DeleteCriticalSection
例子:读者与写者,有一位写者与三位读者,要求当三位读者都读操作完成时写者才能开始写操作,写的过程中不能有任何读者进行读操作。用信号量解决问题
代码如下:
// ReaderAndWriter.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <Windows.h>
#include <stdio.h> int gBook = 0;
CRITICAL_SECTION cs; //线程句柄
HANDLE hThread[4]; //线程体
DWORD WINAPI threadWrite(void *param);
DWORD WINAPI threadRead1(void *param);
DWORD WINAPI threadRead2(void *param);
DWORD WINAPI threadRead3(void *param); //信号量句柄
HANDLE hWriteSM;
HANDLE hRead1SM;
HANDLE hRead2SM;
HANDLE hRead3SM; //线程退出事件
HANDLE hEventWriteExit;
HANDLE hEventRead1Exit;
HANDLE hEventRead2Exit;
HANDLE hEventRead3Exit; /********************************************
程序说明:
一个写线程与三个读线程共同访问gBook,要求当三
个读线程都读完后,写线程才开始写gBook。
主线程等待6秒后通知退出事件,清理资源,结束程序
*********************************************/
int _tmain(int argc, _TCHAR* argv[])
{
//初始化临界区
InitializeCriticalSection(&cs);
//线程退出事件
hEventWriteExit = CreateEvent(NULL, false, false, NULL);
hEventRead1Exit = CreateEvent(NULL, false, false, NULL);
hEventRead2Exit = CreateEvent(NULL, false, false, NULL);
hEventRead3Exit = CreateEvent(NULL, false, false, NULL);
//创建读者写者信号量
hWriteSM = CreateSemaphore(NULL, 0, 3, NULL);//写信号量初始为unsignal ,可知先进行的是读操作
hRead1SM = CreateSemaphore(NULL, 1, 1, NULL);//读信号量初始为signal,
hRead2SM = CreateSemaphore(NULL, 1, 1, NULL);//读信号量初始为signal,
hRead3SM = CreateSemaphore(NULL, 1, 1, NULL);//读信号量初始为signal,
//创建四个线程
hThread[0] = CreateThread(NULL, 0, threadWrite, NULL, 0, NULL);
hThread[1] = CreateThread(NULL, 0, threadRead1, NULL, 0, NULL);
hThread[2] = CreateThread(NULL, 0, threadRead2, NULL, 0, NULL);
hThread[3] = CreateThread(NULL, 0, threadRead3, NULL, 0, NULL);
//等待线程执行6秒
Sleep(1000 * 6);
//发出通知线程结束事件
SetEvent(hEventWriteExit);
SetEvent(hEventRead1Exit);
SetEvent(hEventRead2Exit);
SetEvent(hEventRead3Exit);
//等待四个线程都结束
WaitForMultipleObjects(4, hThread, true, INFINITE);
//关闭句柄,清理资源
CloseHandle(hEventWriteExit);
CloseHandle(hEventRead1Exit);
CloseHandle(hEventRead2Exit);
CloseHandle(hEventRead3Exit); CloseHandle(hWriteSM);
CloseHandle(hRead1SM);
CloseHandle(hRead2SM);
CloseHandle(hRead3SM); for (int i = 0; i < 4; i ++)
CloseHandle(hThread[i]); DeleteCriticalSection(&cs); printf("\t main end \n"); return 0;
} DWORD WINAPI threadWrite(void *param)
{
while(1)
{
DWORD dwWait = WaitForSingleObject(hEventWriteExit, 10);
if (WAIT_TIMEOUT != dwWait)
{
//接收到退出事件后先把资源归还,避免造成死锁
ReleaseSemaphore(hRead1SM, 1, NULL);
ReleaseSemaphore(hRead2SM, 1, NULL);
ReleaseSemaphore(hRead3SM, 1, NULL);
break;
}
WaitForSingleObject(hWriteSM, INFINITE);
WaitForSingleObject(hWriteSM, INFINITE);
WaitForSingleObject(hWriteSM, INFINITE); EnterCriticalSection(&cs);
gBook ++;
printf(" \n Write Process end:%d \n", gBook);
LeaveCriticalSection(&cs); ReleaseSemaphore(hRead1SM, 1, NULL);
ReleaseSemaphore(hRead2SM, 1, NULL);
ReleaseSemaphore(hRead3SM, 1, NULL); Sleep(1000);
} printf("\n******************writer Terminate \n");
return 0;
} DWORD WINAPI threadRead1(void *param)
{
while(1)
{
DWORD dwWait = WaitForSingleObject(hEventRead1Exit, 10);
if (WAIT_TIMEOUT != dwWait)
{
//接收到退出事件后先把资源归还,避免造成死锁
ReleaseSemaphore(hWriteSM, 1, NULL);
break;
}
WaitForSingleObject(hRead1SM, INFINITE);
EnterCriticalSection(&cs);
printf("reader1 process end %d \t", gBook);
LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(100 * 1);
} printf("\n******************read1 Terminate \n");
return 0;
} DWORD WINAPI threadRead2(void *param)
{
while(1)
{
DWORD dwWait = WaitForSingleObject(hEventRead2Exit, 10);
if (WAIT_TIMEOUT != dwWait)
{
//接收到退出事件后先把资源归还,避免造成死锁
ReleaseSemaphore(hWriteSM, 1, NULL);
break;
}
WaitForSingleObject(hRead2SM, INFINITE);
EnterCriticalSection(&cs);
printf("reader2 process end %d \t", gBook);
LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(1000 * 0.5);
} printf("\n******************reader2 Terminate \n");
return 0;
}
DWORD WINAPI threadRead3(void *param)
{
while(1)
{
//接收到退出事件后先把资源归还,避免造成死锁
DWORD dwWait = WaitForSingleObject(hEventRead3Exit, 10);
if (WAIT_TIMEOUT != dwWait)
{
ReleaseSemaphore(hWriteSM, 1, NULL);
break;
}
WaitForSingleObject(hRead3SM, INFINITE); EnterCriticalSection(&cs);
printf("reader3 process end %d \t", gBook);
LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(1000 * 1);
} printf("\n******************reader3 Terminate \n");
return 0;
}
结果如下:
说明:三个读线程读完后,写线程开始写操作,克制结果正确。每次执行时可能结果有所不同,但只有terminate那几行有差异,前面的都相同,原因是当主线程发出通知结束线程事件后,各线程突然跳出,而且无顺序的跳出,线程中等待的时间也有差异,导致这样的结果。