练习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. 【JZOJ4665】数列

    description analysis 水法又\(n\)方二十万-- 可以先离散化,然后枚举起点,枚举向下扫 同一个数出现过或模数不相同就\(break\),注意\(k\)不够顶替还是有可能存在解不 ...

  2. 数据库实例性能调优利器:Performance Insights

    Performance Insights是什么 阿里云RDS Performance Insights是RDS CloudDBA产品一项专注于用户数据库实例性能调优.负载监控和关联分析的利器,以简单直 ...

  3. 分析post与json

    寻找登录的post地址 在form表单中寻找action对应的url地址 post的数据是input标签中name的值作为键,真正的用户名密码作为值的字典,post的url地址就是action对应的u ...

  4. QT中QString与string的转化,解决中文乱码问题

    在QT中,使用QString输出到控件进行显示时,经常会出现中文乱码,网上查了一圈,发现大部分都是针对QT4增加4条语句:</span> [cpp] view plain copy QTe ...

  5. System.Web.UI.WebControls.FileUpload.cs

    ylbtech-System.Web.UI.WebControls.FileUpload.cs 1. 程序集 System.Web, Version=4.0.0.0, Culture=neutral, ...

  6. django2 连接mysql实现第一个rest framework

    1.安装pymysql,mysqlclient,创建项目django-admin startproject django2 2.settings中把DataBase配置换掉 DATABASES = { ...

  7. HTTP协议基础篇(帮助理解)

    用uml 来描述一个功能是怎样按照时间的顺序完成的 实际的需求(配置网站/配置虚拟主机) 步骤 (1) 打开 apache/conf/httpd.conf 文件 (2)找到hosts文件 c:/win ...

  8. <Python基础>python是如何进行内存管理的

    .Python 是如何进行内存管理的?答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制⒈对象的引用计数机制Python 内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用 ...

  9. webpack 简单笔记(二)CommonsChunkPlugin插件

    接下来就要使用CommonsChunkPlugin插件 (一)单一入口,模块单一引用,分文件输出,单一入口,模块重复引用,分文件输 main.js代码 require('./static/js/mai ...

  10. SwiftUI 实现Draggesture效果

    今天闲来无事,使用SwiftUI 实现拖动,并且返回的动态效果.代码不多..... 效果如下: 代码如下: import SwiftUI import Combine class KBDragObje ...