练习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那几行有差异,前面的都相同,原因是当主线程发出通知结束线程事件后,各线程突然跳出,而且无顺序的跳出,线程中等待的时间也有差异,导致这样的结果。

API 练习 第一篇的更多相关文章

  1. 深入理解javascript选择器API系列第一篇——4种元素选择器

    × 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...

  2. 数据库程序接口——JDBC——API解读第一篇——建立连接的核心对象

    结构图 核心对象 Driver Java通过Driver接口表示驱动,每种类型的数据库通过实现Driver接口提供自己的Driver实现类. Driver由属性,操作,事件三部分组成. 属性 公共属性 ...

  3. ElasticSearch查询 第一篇:搜索API

    <ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...

  4. Python爬虫小白入门(四)PhatomJS+Selenium第一篇

    一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...

  5. 我所理解的RESTful Web API [Web标准篇]

    REST不是一个标准,而是一种软件应用架构风格.基于SOAP的Web服务采用RPC架构,如果说RPC是一种面向操作的架构风格,而REST则是一种面向资源的架构风格.REST是目前业界更为推崇的构建新一 ...

  6. 深入理解this机制系列第一篇——this的4种绑定规则

    × 目录 [1]默认绑定 [2]隐式绑定 [3]隐式丢失[4]显式绑定[5]new绑定[6]严格模式 前面的话 如果要问javascript中哪两个知识点容易混淆,作用域查询和this机制绝对名列前茅 ...

  7. ImageJ 学习第一篇

    ImageJ是世界上最快的纯Java的图像处理程序.它可以过滤一个2048x2048的图像在0.1秒内(*).这是每秒40万像素!ImageJ的扩展通过使用内置的文本编辑器和Java编译器的Image ...

  8. [译]PrestaShop开发者指南 第一篇 基础

    # 第一篇 基础 PS(PrestaShop简称)一开始就设定了能够在它的基础上很简单的构建第三方模块的机制,让它成为一款具有极高定制性的电子商务软件. PS的可以在三个方面进行定制: * 主题 * ...

  9. 微信公众账号开发之微信登陆Oauth授权-第一篇

    我曾经在2012年的时候开始研究微信,那时微信的版本还是处于1.0,当时给朋友帮忙做一个基于微信端的web应用,官方的文档是相当少的,百度搜索出来的东西基本也没有多少实用价值,不过是在官网的基础上作了 ...

随机推荐

  1. 家庭-养老院模型理解IOC和DI

    控制反转 IOC 1. 概念 应用内部不负责依赖对象的创建和维护, 由第三方负责, 这样控制权就由应用内部转移到外部容器, 控制权的转移就是所谓的反转. 2. 比喻 有一户家庭(应用)有个老人(依赖对 ...

  2. JQuery Ajax 向后台传参方式

    在jquery的ajax函数中,可以传入3种类型的数据 文本:"uname=alice&mobileIpt=110&birthday=1983-05-12" jso ...

  3. csps模拟87888990部分题解

    题面:https://www.cnblogs.com/Juve/articles/11752338.html https://www.cnblogs.com/Juve/articles/1175241 ...

  4. ECMAScript 6中的Set和Map数据结构

    一.Set 基本用法: Set本身是一个构造函数,用来生成Set数据结构.Set函数可以接受一个数组作为参数用来初始化. const arr = new Set([2,2,3,3,4,4,5,8]); ...

  5. 第十篇:javaScript中的JSON总结

    参考网站:json中国,MDN json 一.必知基础    JSON 是JavaScript对象文字符号的一个子集,它可以自如的在JavaScript中使用.看下这个对象: var myJSONOb ...

  6. Linux负载均衡利器(LVS)

    LVS是什么? LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之 ...

  7. 高性能代理缓存服务器—Squid

    Squid是什么? Squid是一款比较知名的开源代理缓存软件,它不仅可以跑在linux上还可以跑在windows以及Unix上,它的技术已经非常成熟.目前使用Squid的用户也是十分广泛的. Squ ...

  8. django零散知识点

    后端将对象以对象形式传到前端: from django.core.serializers import serialize def xxx(reqeust): project_list = model ...

  9. POJ - 2774~POJ - 3415 后缀数组求解公共字串问题

    POJ - 2774: 题意: 求解A,B串的最长公共字串 (摘自罗穗骞的国家集训队论文): 算法分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长 公共子串等价于求 ...

  10. Linux真好玩阿,不过我家电脑不行,运行不够流畅

    不过呢....能编程就行了....   哎,总说不用QT不用QT,最后还是没办法,用QT了   连个界面都看不到的话,感觉太差了....   我还不会用QT呢....好好学习....争取像MFC那样习 ...