练习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. SpringDataJPA在Entity中常用的注解浅析

    首先我们常用的注解包括(@Entity.@Table.@Id.@IdClass.@GeneratedValue.@Basic.@Transient.@Column.@Temporal.@Enumera ...

  2. springboot mail 发送邮件

    新开发了一个新的功能,要求使用java发送邮件,在此记录下代码,以方便后来者: 1.首先需要开通邮箱,开通smtp功能,我这边使用的是新浪邮箱,试过163.qq,比较麻烦,后来看到别人使用新浪,直接使 ...

  3. ROS 自定义消息类型方法

    流程 1.在package中新建文件夹名为msg 2.在msg文件夹中创建消息(此处以my_msg.msg)为例,注意的是要以msg为后缀名 内容举例如下: int32 data1 float64 d ...

  4. for循环总结

    1.冒泡排序的总结:其实这个很简单的理解,就是用数组里面的第0个元素(也就是[]里面的第一个数,按照数组的话是第一个,让他们进行挨个比较),示例: 排序前: 14 62 38 41 53 62 71 ...

  5. csp-s模拟测试83(集训过半)

    csp-s模拟测试83(集训过半) 一场信心赛.起初$OJ$爆了我就看见全场$A$了$T1$并且夹杂着$A$掉$T2$我就很难受. 这场比赛没有深入思考,很失败,一个多小时后就结束了我罪恶的一生. 0 ...

  6. 关于Async与Await的FAQ

    =============C#.Net 篇目录============== 环境:VS2012(尽管System.Threading.Tasks在.net4.0就引入,在.net4.5中为其增加了更丰 ...

  7. VS2010-MFC(文档、视图和框架:概述)

    转自:http://www.jizhuomi.com/software/221.html 前面几节讲了菜单.工具栏和状态栏的使用,本节开始将为大家讲解文档.视图和框架的知识. 文档.视图和框架简介 在 ...

  8. 执行sql查询,并查看语句执行花费时间

    declare @d datetimeset @d=getdate() select * from A PRINT '[语句执行花费时间(毫秒)]'+LTRIM(datediff(ms,@d,getd ...

  9. js判断客服端

    ua: function () {                    return navigator.userAgent.toLowerCase()                },      ...

  10. Android开发 ExpandableListView 可折叠列表详解

    前言 在需要实现一个List的item需要包含列表的时候,我们就可以选择ExpandableListView. 其实这个View的原始设计还是ListView的那套.就是增加2层的ListView而已 ...