题目大意


有1个资源区,2个缓冲区(大小为1),4个吃货,总共有5个线程,其中一个线程从资源区取字母放到缓冲区,哪个缓冲区是空的就往哪放;4个吃货线程,从缓冲区吃字母。

该题目要求实现对缓冲区的互斥访问,缓冲区和资源区必须满足“缓冲区为空,才能从资源区取字母”的同步要求,缓冲区和吃货线程要满足“缓冲区不空,吃货才能从缓冲区取字母”的同步要求;除此之外,还要求使用信号量控制吃货线程最大并发数为2.

运行结果

代码

// EatChar.cpp : Defines the entry point for the application.
//#include "stdafx.h"HANDLE evtBuffer1Empty, evtBuffer2Empty, evtBuffer1Full, evtBuffer2Full;
HANDLE hSemaphore;
char szBufferRes[100];
char szBuffer1[2], szBuffer2[2];
char szBufferEat[4][100];
HWND hEditEat[4];
HWND hEditRes, hEditBuffer1, hEditBuffer2;
// 负责从资源区取字符,放到缓冲区
// 使用事件实现对缓冲区的互斥访问
// 不使用MUTEX或CRITICAL_SECTION是因为事件能实现同步
// 同步的意思是要确保缓冲区为空才往里面存字符
DWORD WINAPI ThreadCharToBuffer(LPVOID)
{// 只要资源区还有东西,就一直取while (szBufferRes[0] != 0){Sleep(500);// 先看看缓冲区1是否为空,不等待立即返回DWORD dwRet = WaitForSingleObject(evtBuffer1Empty, 0);// 如果1空,那么往1放一个字符if (dwRet == WAIT_OBJECT_0){szBuffer1[0] = szBufferRes[0];//strcpy(szBufferRes, szBufferRes+1);memcpy(szBufferRes, szBufferRes+1, strlen(szBufferRes));SetWindowText(hEditRes, szBufferRes);SetWindowText(hEditBuffer1, szBuffer1);SetEvent(evtBuffer1Full);continue;}else{// 1还有东西,尝试往2里放dwRet = WaitForSingleObject(evtBuffer2Empty, 0);if (dwRet == WAIT_OBJECT_0){szBuffer2[0] = szBufferRes[0];//strcpy(szBufferRes, szBufferRes+1);memcpy(szBufferRes, szBufferRes+1, strlen(szBufferRes));SetWindowText(hEditRes, szBufferRes);SetWindowText(hEditBuffer2, szBuffer2);    SetEvent(evtBuffer2Full);}}     }return 0;
}// 4个线程同时只能有两个被调度,用信号量实现
DWORD WINAPI ThreadEat(LPVOID p)
{// 现在这样写应该有两个线程永远不执行size_t id = (size_t)p;// 信号量控制并发数// 事件控制同步while (szBuffer1[0] != 0 || szBuffer2[0] != 0 || szBufferRes[0] != 0){Sleep(1000);WaitForSingleObject(hSemaphore,INFINITE);// 尝试从1缓冲区取DWORD dwRet = WaitForSingleObject(evtBuffer1Full, 0);if (dwRet == WAIT_OBJECT_0){GetWindowText(hEditEat[id], szBufferEat[id], 100);strcat(szBufferEat[id], szBuffer1);memset(szBuffer1, 0, 2);SetWindowText(hEditBuffer1, szBuffer1);SetWindowText(hEditEat[id], szBufferEat[id]);SetEvent(evtBuffer1Empty);}// 尝试从缓冲区2取else{dwRet = WaitForSingleObject(evtBuffer2Full, 0);if (dwRet == WAIT_OBJECT_0){GetWindowText(hEditEat[id], szBufferEat[id], 100);strcat(szBufferEat[id], szBuffer2);memset(szBuffer2, 0, 2);SetWindowText(hEditBuffer2, szBuffer2);SetWindowText(hEditEat[id], szBufferEat[id]);SetEvent(evtBuffer2Empty);              }}ReleaseSemaphore(hSemaphore, 1, NULL);        }return 0;
}DWORD WINAPI ThreadStart(LPVOID p)
{// 必要的初始化工作memset(szBufferRes, 0, 100);memset(szBuffer1, 0, 2);memset(szBuffer2, 0, 2);GetWindowText(hEditRes, szBufferRes, 100);// 初始化事件:缓冲区为空// 事件句柄应当在资源区为空时关闭evtBuffer1Empty = CreateEvent(0, FALSE, TRUE, NULL);evtBuffer2Empty = CreateEvent(0, FALSE, TRUE, NULL);evtBuffer1Full = CreateEvent(0, FALSE, FALSE, NULL);evtBuffer2Full = CreateEvent(0, FALSE, FALSE, NULL);// 创建1个资源线程HANDLE hThreadCharToBuffer = CreateThread(0,0,ThreadCharToBuffer,0,0,0);// 创建信号量控制并发数和4个吃货线程hSemaphore = CreateSemaphore(0,0,4,0); // 最大资源数4HANDLE hThreadEat[4];hThreadEat[0] = CreateThread(0,0,ThreadEat,(LPVOID)0,0,0);hThreadEat[1] = CreateThread(0,0,ThreadEat,(LPVOID)1,0,0);hThreadEat[2] = CreateThread(0,0,ThreadEat,(LPVOID)2,0,0);hThreadEat[3] = CreateThread(0,0,ThreadEat,(LPVOID)3,0,0);// 释放两个资源,这样同时只能有2个线程被调度ReleaseSemaphore(hSemaphore, 2, 0);WaitForSingleObject(hThreadCharToBuffer, INFINITE);    WaitForMultipleObjects(4, hThreadEat, true, INFINITE);  CloseHandle(evtBuffer1Empty);CloseHandle(evtBuffer2Empty);MessageBox(0,"所有线程结束,所有事件关闭", "", MB_OK);return 0;
}BOOL CALLBACK MainProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{switch(uMsg){case WM_INITDIALOG:{hEditRes = GetDlgItem(hDlg, IDC_EDIT_RES);hEditBuffer1 = GetDlgItem(hDlg, IDC_EDIT_BUFFER1);hEditBuffer2 = GetDlgItem(hDlg, IDC_EDIT_BUFFER2);hEditEat[0] = GetDlgItem(hDlg, IDC_EDIT_A);hEditEat[1] = GetDlgItem(hDlg, IDC_EDIT_B);hEditEat[2] = GetDlgItem(hDlg, IDC_EDIT_C);hEditEat[3] = GetDlgItem(hDlg, IDC_EDIT_D);return TRUE;}case WM_COMMAND:{switch(LOWORD(wParam)){case IDC_BUTTON_START:{HANDLE hThread = CreateThread(0, 0, ThreadStart, 0, 0, 0);CloseHandle(hThread);return TRUE;}}return TRUE;}case WM_CLOSE:{EndDialog(hDlg, 0);return TRUE;}}return FALSE;
}int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR     lpCmdLine,int       nCmdShow)
{DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), 0, MainProc);return 0;
}

WIN32 多线程吃字母练习相关推荐

  1. Win32 多线程的创建方法,区别和联系

    2019独角兽企业重金招聘Python工程师标准>>> Win32多线程的创建方法主要有: CreateThread() _beginthread()&&_begin ...

  2. Win32 多线程学习总结

    Win32多线程编程学习心得 http://blog.csdn.net/jonathan321/article/details/50782832 博客原文地址:http://jerkwisdom.gi ...

  3. Win32多线程编程(3) — 线程同步与通信

    一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线程的 ...

  4. Win32多线程编程(1) — 基础概念篇

    内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Servic ...

  5. 深入浅出Win32多线程程序设计之线程通信

    简介 线程之间通信的两个基本问题是互斥和同步. 线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒. 线程互斥是 ...

  6. Win32多线程之被激发的对象(Signaled Objects)

    核心对象在"Win32多线程之核心对象"已经讲过,如文件,进程,互斥器(Mutexes)等.这些对象的状态都可能是线程关心的东西.信号量(semaphores)和互斥器(mutex ...

  7. 吃字母------线程同步与互斥的学习

    线程的同步与互斥的实战----吃字母 希望能给你一些启发: 我们在资源输入数据,下面的两个缓冲区,通过线程获取资源的数据,吃货A-D 抢 两个缓冲区的数据 并放入对应的数据栏中. 例如: 解决思想和方 ...

  8. Win32多线程调用gdal库接口

    作者:朱金灿 来源:clever101的专栏 为什么大多数人学不会人工智能编程?>>> 效果图和程序说明   效果图如下:   这个程序是基于MFC的GUI程序,用于给指定的文件夹批 ...

  9. 深入浅出Win32多线程程序设计

    引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的成员员也只能通过驻留内存的方式实现所谓的"多任务",而如今的Win32操 ...

最新文章

  1. 详解vue 路由跳转四种方式 (带参数)
  2. linux /etc/fstab 挂载列表 简介
  3. 用栈实现队列和用队列实现栈
  4. 里写注释 postman_没用过这些IDEA插件?怪不得写代码头疼
  5. python sum函数numpy_如何用numba加速python?
  6. android sqlite 多对多,SQLite多对多的关系?
  7. 帝国cms 6.6 采集入库多记录时出现空白 解决办法
  8. [转载]使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放...
  9. 《tcpip详解》卷一第2章
  10. adobe flash builder 4.6最新能用的序列号
  11. linux phpstudy卸载,linux 安装phpstudy
  12. 【渝粤题库】陕西师范大学200931小学语文教学论 作业(高起专)
  13. 如何开通支付宝小程序助手?
  14. c语言中要求五个数一行,c 语言中如何一行输出五个数
  15. responserequest概述
  16. 数据分析---------指数计算
  17. trac mysql_无法加载MySQL的Python绑定 – Trac
  18. 百分点认知智能实验室:智能校对的技术原理和实践
  19. MySQL数据库集群实现负载均衡的安装配置详解
  20. BASH脚本基础:环境变量PS2介绍

热门文章

  1. DL之RNN:人工智能为你写代码——基于TF利用RNN算法实现生成编程语言代码(C++语言)、训练测试过程全记录
  2. Ubuntu16.04 安装R与RStudio
  3. 用 javascript 获取当页面上鼠标(光标)位置
  4. 第二次周考题目答案整理
  5. 从零开始搭建系统1.1——CentOs安装
  6. jQuery避免$符和其他JS库冲突的方法对比
  7. ios:CGContextRef 渲染中文问题
  8. Spring mvc 转发、重定向
  9. iOS RunLoop 初识
  10. 标记【新公司】!!!!!!!!!!