API 练习 第一篇

练习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;
}

 

 

结果如下:

API 练习 第一天 - 快乐男孩 - work labor and play
说明:三个读线程读完后,写线程开始写操作,克制结果正确。每次执行时可能结果有所不同,但只有terminate那几行有差异,前面的都相同,原因是当主线程发出通知结束线程事件后,各线程突然跳出,而且无顺序的跳出,线程中等待的时间也有差异,导致这样的结果。

 

posted on 2018-10-08 11:38  priarieNew  阅读(448)  评论(0编辑  收藏  举报

导航