练习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(" main end "); 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(" Write Process end:%d ", gBook); LeaveCriticalSection(&cs); ReleaseSemaphore(hRead1SM, 1, NULL); ReleaseSemaphore(hRead2SM, 1, NULL); ReleaseSemaphore(hRead3SM, 1, NULL); Sleep(1000); } printf(" ******************writer Terminate "); 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 ", gBook); LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(100 * 1); } printf(" ******************read1 Terminate "); 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 ", gBook); LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(1000 * 0.5); } printf(" ******************reader2 Terminate "); 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 ", gBook); LeaveCriticalSection(&cs); ReleaseSemaphore(hWriteSM, 1, NULL); Sleep(1000 * 1); } printf(" ******************reader3 Terminate "); return 0; }
结果如下:
![API 练习 第一天 - 快乐男孩 - work labor and play](http://img2.ph.126.net/rLngD8q4AcuNh-Q5TrokNg==/6630792887794266908.jpg)
说明:三个读线程读完后,写线程开始写操作,克制结果正确。每次执行时可能结果有所不同,但只有terminate那几行有差异,前面的都相同,原因是当主线程发出通知结束线程事件后,各线程突然跳出,而且无顺序的跳出,线程中等待的时间也有差异,导致这样的结果。