多线程学习(一)----CreateThread
// tt.cpp : 定义控制台应用程序的入口点。
//同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等,但是同一个进程中的多个线程都有各自的调用栈、寄存器环境和线程本地存储。
//线程都拥有自己的堆栈,临界区等主要是控制访问全局变量和成员变量
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#define WM_NIHAO 1001
#define THREADNUM 3
/*
volatile 修饰符的作用是告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。
对于多线程引用的全局变量来说,volatile 是一个非常重要的修饰符。
*/
volatile int gInt=0;
//普通临界区
static CRITICAL_SECTION cs;
//MFC临界区
//CCriticalSection ccs;
//使用原子操作的方法
volatile LONG aomic=100;
void fun(int tNum)
{
//printf("第%d线程已经工作了\n",tNum);
if (1)
{
//临界区
EnterCriticalSection(&cs);// 进入临界区,其它线程则无法进入
//ccs.Lock();
// 安全访问该区域
gInt--;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
Sleep(0);//致使不使用临界区肯定出错的方法
gInt++;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
//ccs.Unlock();
LeaveCriticalSection(&cs); // 离开临界区,其它线程可以进入
//原子操作
InterlockedIncrement(&aomic);
InterlockedDecrement(&aomic);
}
MSG msg;
//GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。
//GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
//返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。
while(1)
{
int tGM=::GetMessage(&msg,NULL,0,0);
switch(msg.message)
{
case WM_NIHAO:
printf("第%d线程接收到主线程的发过来的消息:%s\n",tNum,(char*)msg.wParam);
break;
default:
break;
}
//不需要接收第二次消息
if (tGM>0)
{
break;
}
}
printf("%d线程结束",tNum);
//该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
//ExitThread(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
// 在进入多线程环境之前,初始化临界区
InitializeCriticalSection(&cs);
DWORD threadId[THREADNUM];
HANDLE hThread[THREADNUM];
for (int i=0;i<THREADNUM;i++)
{
hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
}
while (getch()!='1')
{
Sleep(100);
}
//试探线程读取全局变量
gInt=100;
for (int i=0;i<THREADNUM;i++)
{
if (-1==ResumeThread(hThread[i]))
{
printf("ResumeThread时候出错了\n");
return -1;
}
}
//ResumeThread线程之后线程投入工作需要一定时间
Sleep(1000);
char buff[20]="ni hao ma?";
for (int i=0;i<THREADNUM;i++)
{
BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
}
//参数一:线程句柄
//参数二:等待时间(毫秒),IGNORE:不等,INFINITE:死等
//返回值: WAIT_OBJECT_0: 线程结束
// WAIT_TIMEOUT:超过等待时间,指定的对象处于无信号状态
// WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll为TRUE,则返回值表明所有指定对象的状态是触发的,并且至少对象之一,是一个废弃的互斥对象。
// WAIT_FAILED:出现错误,一般是线程句柄错误
//WaitForSingleObject函数,此函数的作用是监视hHandle的状态,当监视的句柄为有信号状态时,即此对象为空闲状态时,此函数返回,才能执行其后的代码。
//WaitForSingleObject(hThread,INFINITE);
Sleep(1000);
//值得注意的是hThread数组的所有成员必须全部有效,有一个没效的话,次函数就会执行失败
DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
//若果第三个参数是true,则返回值代表所有线程的状态
//若果第三个参数是false,则返回值代表那个有返回线程的状态
switch (wm)
{
case WAIT_FAILED:
printf("wm-->WAIT_FAILED\n");
break;
case WAIT_TIMEOUT:
printf("wm-->WAIT_TIMEOUT\n");
break;
case WAIT_ABANDONED_0+0:
case WAIT_ABANDONED_0+1:
case WAIT_ABANDONED_0+2:
printf("wm-->WAIT_ABANDONED_0\n");
break;
case WAIT_OBJECT_0+0:
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
printf("wm-->WAIT_OBJECT_0\n");
break;
default:
break;
}
//一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。
for (int i=0;i<THREADNUM;i++)
{
TerminateThread(hThread[i],0);
}
// 释放临界区资源,当不再使用临界区时调用该函数
DeleteCriticalSection(&cs);
return 0;
}
多线程学习(一)----CreateThread相关推荐
- Delphi多线程详解CreateThread、TThread,以及线程间通过临界区(CriticalSection)实现同步
在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:ht ...
- Java多线程学习处理高并发问题
在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结. 以下内容将 ...
- C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 艾伟:C#多线程学习(六) 互斥对象
本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...
- C# 多线程学习总结
C#多线程学习(一) 多线程的相关概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是 ...
- C#多线程学习(二) 如何操纵一个线程
C#多线程学习(二) 如何操纵一个线程 原文链接:http://kb.cnblogs.com/page/42529/ [1] C#多线程学习(二) 如何操纵一个线程 [2] C#多线程学习(二) 如何 ...
- 多线程学习-基础(四)常用函数说明:sleep-join-yield
一.常用函数的使用 (1)Thread.sleep(long millis):在指定的毫秒内让当前正在执行的线程休眠(暂停执行),休眠时不会释放当前所持有的对象的锁. (2)join():主线程等待子 ...
- C#多线程学习之(五)使用定时器进行多线程的自动管理
本文实例讲述了C#多线程学习之使用定时器进行多线程的自动管理.分享给大家供大家参考.具体分析如下: Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执 ...
- java多线程学习-java.util.concurrent详解
http://janeky.iteye.com/category/124727 java多线程学习-java.util.concurrent详解(一) Latch/Barrier 博客分类: java ...
- C#多线程学习(三) 生产者和消费者
C#多线程学习(三) 生产者和消费者 原文链接:http://kb.cnblogs.com/page/42530/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操 ...
最新文章
- CSS中浮动布局float(小米布局案例、导航栏案例、overflow)
- 高斯-赛德尔迭代法简介
- 主成分分析的数学原理
- sql server charindex函数和patindex函数详解(转)
- 如何学习开源项目及Ceph的浅析
- java怎样写入五个人的成绩_用java输入5个学员姓名和分数,显示分数最高的学员姓名和分数?...
- STL(二)——向量vector
- 爬取豌豆荚app数据(总结篇)
- Pytorch模型量化介绍
- STM32开发 | 移远4G-Cat.1模组EC200N-CN开发
- 校园一角 四年级计算机课,校园一角的四年级作文5篇
- 重磅发布 | 图像图形学发展年度报告【中国图象图形学报第6期综述专刊】
- 概率论中一个有趣的问题-------双六问题
- 游戏建模:21个人脑壳雕刻小小技巧,非常有用!
- 华光昱能光知识-细说MPO光纤跳线那些事
- 新旧电脑安装win11系统【超简单教程】
- 用NDK-r25编译libpng
- 【linux】重新启动项目
- wordpress建站准备教程(一)域名:域名备案、域名注册、域名绑定、域名解析
- web项目:智能出行规划网站——爬虫+flask+echarts+基础前端(html、css、js、jq)
热门文章
- 数据库-优化-MYSQL数据库设计原则
- 解决2次查询User的问题(ThreadLocal)
- Zuul:Cookie和动态路由
- SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)
- java的自动装配是什么意思_java – 什么时候在Spring中使用自动装配
- 判断ipad还是安卓_?谷歌认输,iPad或成唯一赢家,安卓平板路在何方?
- PHP 梯形图,学习PLC,不要先翻资料,干就完了.搞起你的第一个梯形图.
- 一步一步了解Promise原理
- vCenter 6.0安装部署
- Linux打tar包排除目录中的某个目录