// MultiThread.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <process.h>
using namespace std;CRITICAL_SECTION g_csA;
CRITICAL_SECTION g_csB;UINT WINAPI PrintThread1(LPVOID lp)
{while (1){//该代码段最后看,用信号量实现10个线程同步有序//if (WaitForSingleObject(g_hDemaphore, INFINITE) != WAIT_OBJECT_0)//{//continue;//}//EnterCriticalSection(&g_csA);for (int i=0;i<3;i++){printf("thread1\n");Sleep(1000);}printf("\n");LeaveCriticalSection(&g_csA);}return 0;
}UINT WINAPI PrintThread2(LPVOID lp)
{while (1){EnterCriticalSection(&g_csA);for (int i=0;i<3;i++){printf("thread2\n");Sleep(100);}printf("\n");LeaveCriticalSection(&g_csA);}return 0;
}
///
HANDLE g_hEvent;
UINT WINAPI PrintThread3(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hEvent, INFINITE);if (dwResult == WAIT_OBJECT_0){for (int i=0;i<3;i++){printf("thread3\n");Sleep(500);}printf("\n");}SetEvent(g_hEvent);}return 0;
}UINT WINAPI PrintThread4(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hEvent, INFINITE);if (dwResult == WAIT_OBJECT_0){for (int i=0;i<3;i++){printf("thread4\n");Sleep(300);}printf("\n");}SetEvent(g_hEvent);}return 0;
}///
HANDLE g_hMutex;
UINT WINAPI PrintThread5(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hMutex, 500);//当前线程拥有该互斥量if (dwResult == WAIT_OBJECT_0){for (int i=0;i<3;i++){printf("thread5\n");Sleep(200);}printf("\n");}if (!ReleaseMutex(g_hMutex))//当前线程释放该互斥量{DWORD dwError = GetLastError();if (dwError == ERROR_NOT_OWNER){printf("thread5 error:ERROR_NOT_OWNER\n");}else{printf("thread5 error:%d\n", dwError);}}}return 0;
}UINT WINAPI PrintThread6(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hMutex, 1000);if (dwResult == WAIT_OBJECT_0){for (int i=0;i<3;i++){printf("thread6\n");Sleep(400);}printf("\n");}if (!ReleaseMutex(g_hMutex)) //如果互斥量被线程5占有,那么当前线程将无法释放,只有占有者可以释放{DWORD dwError = GetLastError();if (dwError == ERROR_NOT_OWNER){printf("thread6 error:ERROR_NOT_OWNER\n");}else{printf("thread6 error:%d\n", dwError);}}}return 0;
}
//
HANDLE g_hDemaphore;
UINT WINAPI PrintThread7(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);//占用一个资源计数if (dwResult == WAIT_OBJECT_0){printf("Anglela");Sleep(1000);}LONG count;ReleaseSemaphore(g_hDemaphore,1,&count);//释放一个资源计数}return 0;
}UINT WINAPI PrintThread8(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);//减少一个资源计数(如果还有资源计数)if (dwResult == WAIT_OBJECT_0){printf("Baby\n");printf("\n");Sleep(1000);}LONG count;ReleaseSemaphore(g_hDemaphore,1,&count);//增加一个资源计数Sleep(2000);// 减少后并不立即增加}return 0;
}UINT WINAPI PrintThread9(LPVOID lp)
{while (1){DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);Sleep(1000);if (dwResult == WAIT_OBJECT_0){printf("Alice ");Sleep(500);}LONG count;BOOL bFlag = ReleaseSemaphore(g_hDemaphore,3,&count);if (!bFlag){printf("\n");printf("thread9 release failed:%d\n", GetLastError());}}return 0;
}UINT WINAPI PrintThread10(LPVOID lp)
{DWORD dwResult = 0;while (1){//减少2个资源计数dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);if (dwResult == WAIT_OBJECT_0){printf("in Wonderland\n");printf("\n");Sleep(1000);}::EnterCriticalSection(&g_csB);LONG count;// if rcount+pcount>maxcount,增加资源计数失败且当前资源计数不变BOOL bFlag = ReleaseSemaphore(g_hDemaphore,2/*relasecount*/,&count/*previous count*/);//增加2个资源计数if (!bFlag){printf("\n");printf("thread10 release failed:%d\n", GetLastError());}printf("thread10 previous count:%d\n", count);//执行release以前的资源计数::LeaveCriticalSection(&g_csB);}return 0;
}// 除了临界区,其他为内核对象,除了用于线程还可用于进程,可以通过创建时指定的名字打开夸进程使用
//
int _tmain(int argc, _TCHAR* argv[])
{InitializeCriticalSection(&g_csA);InitializeCriticalSection(&g_csB);HANDLE m_hThread = NULL;//同步与互斥:‘1个生产者-N个消费者’模型,同步有序-必须先生产然后消费,互斥无序,要么执行A,要么执行B,AB顺序未知//由于线程1比线程2先执行,临界区保证打印结果thread1,thread2有序//m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread1, NULL, 0, NULL);//m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread2, NULL, 0, NULL);//使用事件控制线程3,4有序执行//创建一个命名的自动重置事件内核对象,第二个参数FALSE指定自动重置,第三个参数TRUE设置初始化为有信号g_hEvent=CreateEvent(NULL,FALSE,TRUE,LPCWSTR("myevent"));if (g_hEvent){if (ERROR_ALREADY_EXISTS==GetLastError()){printf("error:event alread exist\n");}}// 可以打开其他进程创建的事件对象//$ g_hEvent = OpenEventA(EVENT_ALL_ACCESS, TRUE, LPCWSTR("myevent"));//$ ResetEvent(g_hEvent);//m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread3, NULL, 0, NULL);//m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread4, NULL, 0, NULL);//第二个参数TRUE,main线程拥有互斥量,体现互斥量‘线程拥有’的概念,区别事件‘先到先得’g_hMutex = CreateMutexA(NULL, TRUE, "mymutex");//$ g_hMutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, "mymutex");/*m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread5, NULL, 0, NULL);m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread6, NULL, 0, NULL);//$ 事件对象设置为自动重置与互斥量有类似功能Sleep(3000);printf("main thread release mutex\n");printf("\n");ReleaseMutex(g_hMutex);*/// 信号量体现‘资源计数’的概念,通过修改初始计数与释放增加计算使打印有序// SEMAPHORE_MODIFY_STATE,初始资源计数为2时,信号量为有信号状态,最大允许资源计数为10时,信号量为有信号状态g_hDemaphore=CreateSemaphoreA(NULL,2,10,("Sem"));//初始资源计数为1,最大允许资源计数为2,通过release增加资源计数//$ HANDLE semaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, _T("Global\\TestSemaphore"));m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread7, NULL, 0, NULL);m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread8, NULL, 0, NULL);m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread9, NULL, 0, NULL);m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread10, NULL, 0, NULL);while (getchar()!='x'){}DeleteCriticalSection(&g_csA);DeleteCriticalSection(&g_csB);CloseHandle(m_hThread);CloseHandle(g_hEvent);if (WaitForSingleObject(g_hMutex, 0) == WAIT_ABANDONED){ReleaseMutex(g_hMutex);}CloseHandle(g_hMutex);return 0;
}

1.线程1,2实现打印thread1,thread2有序,thread3~thread6实现类似打印功能;

2.线程7,8,9,10实现打印两个有序字符串,通过修改初始计数与增减计数实现打印有序;

3.MFC将4方法封装4个类功能相同,除了临界区,其他3个可以进程间使用。

临界区、事件、互斥量、 信号量--四种控制多线程同步与互斥的方法相关推荐

  1. 秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

    前面<秒杀多线程第四篇一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,这个问题包括了主线程与子线程的同步,子线程间的互斥,是一道非常经典的多线程同步互斥问题范例,后面分别用了 ...

  2. 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

    秒杀多线程第十五篇 关键段,事件,互斥量,信号量的"遗弃"问题 在<秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量>中对经典多线程同步互斥问题进行了回 ...

  3. 经典线程同步总结 关键段 事件 互斥量 信号量

    本文参考了http://blog.csdn.net/morewindows/article/details/7538247 1.线程(进程)同步的主要任务 答:在引入多线程后,由于线程执行的异步性,会 ...

  4. Linux 多线程同步机制:互斥量、信号量、条件变量

    互斥量:互斥量提供对共享资源的保护访问,它的两种状态:lock和unlock,用来保证某段时间内只有一个线程使用共享资源,互斥量的数据类型是pthread_mutex_t 主要涉及函数:pthread ...

  5. 深入解析react关于事件绑定this的四种方式

    这篇文章主要介绍了详解react关于事件绑定this的四种方式,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. 在react组件中,每个方法的上下 ...

  6. JMeter-两种控制Sampler执行线程数量的方法

    JMeter-两种控制Sampler执行线程数量的方法 一.如果(If)控制器 (1)添加"如果(If)控制器",并在控制器中填写判断语句: ${__groovy(${__coun ...

  7. win10运行在哪里打开_Win10在哪里卸载软件程序?Win10四种正确卸载软件或者游戏的方法...

    如今Win10系统已经是目前主流的操作系统,各个功能都十分完善了,可能熟悉Win7或者XP的朋友,刚刚开始使用Win10操作系统的一些朋友,连卸载软件程序都不知道怎么卸载,找不到地方.那么Win10在 ...

  8. php订单怎么生成,四种PHP生成唯一订单号的方法

    这几天一直在写个人使用的用户中心,虽然期间遇到不少的问题,但还是一点点的都解决了,也从制作期间学到不少的知识,今天就说一说利用PHP生成订单单的方法. 订单号,大家都不陌生,无论从在网上购物,还是在线 ...

  9. 关于多线程同步与互斥

    原文:看我稳住「多线程」翻车的现场!_小林coding-CSDN博客 文章目录 前言 正文 竞争与协作 互斥的概念 同步的概念 互斥与同步的实现和使用 锁 信号量 生产者-消费者问题(互斥+同步) 经 ...

最新文章

  1. 可执行SQL文的mybatis工具类
  2. 重新定义“人货场”:淘宝情景计算探索实践
  3. 支持CDS view的SAP ALV IDA - 使用前提
  4. 斜齿轮啮合 matlab,渐开线斜齿轮曲面精确建模及MatLab仿真
  5. 用php写的亲亲鲜花网站_php54鲜花销售网站
  6. Spring Security(5):自定义决策
  7. Microsoft Bot Builder Overview
  8. 五、Mysql中JSON类型
  9. 集群间动态扩展和删除hdfs的datanode和hbase的regionserver
  10. Mysql管理之二进制日志文件的管理
  11. Redis面经:重新梳理了 5 种数据类型的用法和应用场景
  12. 飞控中的一些知识点总结
  13. 浅谈Struts2拦截器的原理与实现
  14. Java爬取frame的课程表_超级课程表一键提取课程功能app及课表静态网页内容
  15. bootstrap v4 toast轻提示正确用法
  16. 华硕h81m一k跳线图_主板跳线接法
  17. tableau关于增长率、占比的表计算实践应用
  18. node解决安装包后xx-v命令无效
  19. 对于无线传感网的初步认识
  20. [解决] 警告: 未来的版本中将会删除 NARGCHK。请改用 NARGINCHK 或 NARGOUTCHK。

热门文章

  1. php远程开机ubuntu,Ubuntu系统远程开机操作实例
  2. 漫谈promise使用场景
  3. 数据结构实验之二叉树六:哈夫曼编码
  4. 谁是最强的女汉子_JAVA
  5. win10下vs2015编译的程序如何运行在win7等系统(无需安装Redistributable)
  6. 【自动驾驶】视觉里程计
  7. Java 性能优化之 String 篇
  8. 俯卧撑打造男人结实臂膀
  9. Hadoop与Spark常用配置参数总结
  10. OpenCV学习笔记资料大集锦