练习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. Python 输入字符串找(String)下标 没有返回-1

    str = "abcdefg123456"a = input("请输入一个字母或数字:")num = 0result = -1while num < le ...

  2. agc38C LCMs

    https://atcoder.jp/contests/agc038/tasks/agc038_c 题意:给\(a_i\),求\(\sum_{i=1}^n\sum_{j=i+1}^nlcm(a_i,a ...

  3. hdu多校第二场 1005 (hdu6595) Everything Is Generated In Equal Probability

    题意: 给定一个N,随机从[1,N]里产生一个n,然后随机产生一个n个数的全排列,求出n的逆序数对的数量,加到cnt里,然后随机地取出这个全排列中的一个非连续子序列(注意这个子序列可以是原序列),再求 ...

  4. 最大流dicnic——hdu1532模板题

    #include<bits/stdc++.h> using namespace std; #define maxn 1005 #define ll long long const ll i ...

  5. Delphi窗体间发送消息或字符串

    在Delphi 开发中,常常应用到窗体消息传递,以达成某种操作要求,以下列举一个应用的例子,供大家参考. 自定义过程/函数方法://发送字符串到指字句柄的窗口中 (接收窗体需用发送时的消息常量WM_C ...

  6. python相关软件安装流程图解——虚拟机操作——复制虚拟机主机——CentOS-7-x86_64-DVD-1810

    请先确保已经安装了虚拟机 python相关软件安装流程图解——虚拟机安装——CentOS-7-x86_64-DVD-1810——CentOS-01下载 https://www.cnblogs.com/ ...

  7. Mybatis笔记 – 入门程序开发

    一.Mybatis开发环境 JDK:jdk_1.7 Eclipse:Oxygen.1 Release (4.7.1) MySQL:MySQL Servr 5.7 1.添加相关ja r包 mybatis ...

  8. QT 在QTabWidget中设置一些调色板

    这次所做的项目中需要用到如下功能,点击tableWidget中的子项,将会弹出颜色选值对话框,实现子项的改变,如下图所示: 1.首先,将自己定制的调色板放入tableWidget中 for (int ...

  9. 《DSP using MATLAB》Problem 8.35

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  10. 20.multi_case02

    # 多进程,使用Process对象 from multiprocessing import Process def f(name): print('hello', name) if __name__ ...