#include "stdafx.h"
#include <windows.h>
#include <process.h> int g_count;
const int ThreadNum = ;
unsigned int __stdcall Func(LPVOID pm)
{
int id = *(int*)pm;
Sleep();
g_count++;
printf_s("id=%d,count=%d \n", id, g_count);
return ;
} int main()
{
HANDLE handle[ThreadNum];
g_count = ;
for (int i = ; i < ThreadNum; ++i)
{
handle[i] = (HANDLE)_beginthreadex(NULL, , Func, (LPVOID)&i, , NULL);
}
WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);
system("pause");
return ;
}

要求:

子线程输出的线程序号不能重复。(主线程和子线程需要同步)

全局变量g_count的输出必须递增。(子线程之间需要互斥)

1,用临界区CRITICAL_SECTION来解决子线程之间的互斥

CRITICAL_SECTION g_section;//声明一个临界区资源
InitializeCriticalSection(&g_section);//初始化
EnterCriticalSection(&g_section);//开始进入临界区代码段
LeaveCriticalSection(&g_section);//离开临界区代码段
DeleteCriticalSection(&g_section);//销毁
#include "stdafx.h"
#include <windows.h>
#include <process.h> int g_count;
const int ThreadNum = ;
CRITICAL_SECTION g_section;
unsigned int __stdcall Func(LPVOID pm)
{
int id = *(int*)pm;
Sleep();
EnterCriticalSection(&g_section);//进入临界区后各个线程之间互斥
g_count++;
//InterlockedIncrement((LPLONG)&g_count);
printf_s("id=%d,count=%d \n", id, g_count);
LeaveCriticalSection(&g_section);
return ;
} int main()
{
InitializeCriticalSection(&g_section);
HANDLE handle[ThreadNum];
g_count = ;
for (int i = ; i < ThreadNum; ++i)
{
handle[i] = (HANDLE)_beginthreadex(NULL, , Func, (LPVOID)&i, , NULL);
}
WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);
DeleteCriticalSection(&g_section);
system("pause");
return ;
}

2用事件解决主线程和子线程的同步问题

//CreateEvent创建一个事件

HANDLE CreateEvent(

LPSECURITY_ATTRIBUTES lpEventAttributes,//安全参数,一般为NULL

BOOL bManualReset, //TRUE手动(SetEvent后需要ResetEvent) , FALSE自动,对事件对象调用WaitForSingleObject后自动是对象变成未触发的状态

BOOL bInitialState, //TRUE 初始状态就是触发状态

LPCTSTR lpName //事件对象的名字,传入NULL表示匿名的事件对象

);

//SetEvent 触发一个事件内核对象,必有一个或者多个等待状态的线程变成可调度的状态

BOOL SetEvent(HANDLE hEvent);

//ResetEvent 事件变成未触发状态

BOOL ResetEvent (HANDLE hEvent);

最后的代码如下

#include "stdafx.h"
#include <windows.h>
#include <process.h> int g_count;
const int ThreadNum = ;
CRITICAL_SECTION g_section;
HANDLE g_handle; unsigned int __stdcall Func(LPVOID pm)
{
int id = *(int*)pm;
SetEvent(g_handle);//事件被触发后,线程变成可调度状态
Sleep();
EnterCriticalSection(&g_section);//进入临界区
g_count++;
printf_s("id=%d,count=%d \n", id, g_count);//离开临界区
LeaveCriticalSection(&g_section);
return ;
} int main()
{
g_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
InitializeCriticalSection(&g_section); HANDLE handle[ThreadNum];
g_count = ;
for (int i = ; i < ThreadNum; ++i)
{
handle[i] = (HANDLE)_beginthreadex(NULL, , Func, &i, , NULL);
WaitForSingleObject(g_handle, INFINITE);//等待事件被触发
}
WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);//等待所有的子线程被触发
CloseHandle(g_handle);
DeleteCriticalSection(&g_section);
system("pause");
return ;
}

输出

id没有相同的,说明主线程和子线程之间已经同步,

count递增,说明子线程之间已经互斥

C++多线程3的更多相关文章

  1. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  2. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  3. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  4. Java多线程

    一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程.   进程:进程 ...

  5. .NET基础拾遗(5)多线程开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  6. Java多线程基础——对象及变量并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  7. C#多线程之线程池篇3

    在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...

  8. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  9. C#多线程之线程池篇1

    在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...

  10. C#多线程之线程同步篇3

    在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...

随机推荐

  1. GitHUb 代码提交遇到的问题以及解决办法

    git 添加代码出现以下错误: fatal: Unable to create 'F:/wamp/www/ThinkPhpStudy/.git/index.lock': File exists. If ...

  2. mybatis入门_配置文件的配置

    一.全局配置文件配置 1.1 properties标签 Properties标签可以用来加载配置文件.例如,我们可以将数据库的连接信息放入到一个配置文件(db.properties中..) 下为db. ...

  3. 一个View的子类实例化

    View子类的实例化.如果是在activity中通过findViewById的形式实例化,那么它的具体的构造函数是什么呢,看看父类View的源码就容易发现是 通过这个构造函数实例化的 public V ...

  4. settings.php rwx

    440/400 https://www.drupal.org/node/137702 You must understand the meaning of XYZ chmod from file at ...

  5. mysql-5.7.9安装

    版本:mysql-5.7.9-linux-glibc2.5-x86_64.tar.gz(编译版本) 解压: tar -zxvf mysql-5.7.9-linux-glibc2.5-x86_64.ta ...

  6. DOM hash

    前段时间做的一个H5专题,用到了hash解决问题,特意记录一下.DOM hash的详细内容可以点击链接查看. hash就是uri中#及后面的部分,例如:www.google.com.hk#123的#1 ...

  7. Sublime Text 2 代码片断

    原文:Snippets 不管是在编码,还是写畅销书,你都可能会需要一遍又一遍的用到一些文本的小片断.使用片断来结束这种单调无聊的码字吧,片断是一种智能的模板,它能在合适的上下文中插入你需要的文本内容. ...

  8. 安装pear

    下载go-pear.phar php go-pear.phar pear install Mail-1.2.0 pear list

  9. C# Socket连接 无法访问已释放的对象

    在进行Socket长连接时,若服务器或客户端出现异常时,另外一端对Socket对话进行操作时,程序会出现无法访问已释放的对象的问题.例如客户端出现问题主动断开Socket时,当服务器操作Socket时 ...

  10. 《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第四章自学笔记 进程调度 By20135203齐岳 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵 ...