CreateThread简单那多线程编程
作者:vpoet
mail:vpoet_sir@163.com

在进行多任务处理的时候我们往往会用到多线程技术,多线程理论上是多个线程同事处理不同的工作,但是这只针对多核的CPU而言
但是对于单核CPU多线程往往实现的方式是:CPU为各个线程分配时间片,让各个线程循环的执行,但是这个时间片又很短,所以给我
们只管的映像就好像是多个线程在同时工作。
本文主要使用windows API CreateThread函数进行多线程演示。
首先看看MSDN上关于CreateThread函数的说明:
参数说明:
lpThreadAttributes [in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If
lpThreadAttributes is NULL, the handle cannot be inherited. 
该参数决定子线程是否继承父进程的安全属性,如果为NULL,表示不继承。关于SECURITY_ATTRIBUTES结构体请查询MSDN
dwStackSize [in] Specifies the initial commit size of the stack, in bytes. The system rounds this value to the nearest page. If this value is zero, or is smaller than the default commit size, the default is to use the same size as the calling thread. For more information,
see Thread Stack Size
该参数指定线程堆栈大小,如果该值为零则使用默认的线程堆栈大小
lpStartAddress [in] Pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread. For more information on the thread function, see
ThreadProc
该参数则指定线程函数地址,说白了就是线程函数名
lpParameter [in] Specifies a single parameter value passed to the thread. 
该参数为传递给线程函数的参数
dwCreationFlags [in] Specifies additional flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state, and will not run until the
ResumeThread function is called. If this value is zero, the thread runs immediately after creation. At this time, no other values are supported. 
该参数为创建标识,如果为零,那么线程创建后会立即执行,若为CREATE_SUSPENDED则线程创建后则会停止
lpThreadId [out] Pointer to a variable that receives the thread identifier. 
该参数为创建线程的线程ID,线程ID就是唯一标识该线程的一个数字

那么现在我们来写一个最简单的多线程例子:

#include <windows.h>
#include "stdio.h" DWORD WINAPI ThreadOne(LPVOID lpParameter)
{
printf("ThreadOne is Runing\n");
Sleep(100);
return 0;
} int main()
{
HANDLE HOne;
printf("***********************vpoet******************\n");
HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
printf("ThreadOne Begin!\n");
CloseHandle(HOne);
printf("MainThread Over!\n");
return 0;
}

运行结果:
咦!是不是看出来什么问题了,子线程貌似没有运行主线程就退出了,这是怎么回事呢,这说明当开启子线程后还未来得及运行主线程就已经执行完毕,并且return了,那么此时整个程序也就退出,当然也就不会再运行子线程了。那么我们应该怎么控制了,既然子线程来不及执行,那么我就让主线程多运行一会儿等到子线程执行完了之后主线程再退出。是不是很有道理,恩,我也觉得。
那么我们在

printf("MainThread Over!\n");

之前再加入一句代码

Sleep(1000)

让主线程延时1s等待子线程的执行。因为1s足够让子线程执行完毕了所以这次程序就会在子线程运行结束后正常退出了。运行结果如下:
看吧,这下是正常退出了吧。

当然还有其他方法来等待子线程正常执行并返回,对了还有个HOne这玩意儿还没有介绍,
Handle其实就是一个句柄对象,就像是一个结构体或者类一样,只不过它是内核对象,由内核
自己维护。为啥需要CloseHand()呢 百度百科是这样说的:
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。

那么我们就需要知道线程到底是什么时候退出的呢,然后在其退出的时候把该线程句柄Close掉。

这里要介绍一个API叫WaitForSingleObject;
我们MSDN一下:

MSDN这样说该函数只有在以下两种情况下才返回:
1.指定的对象有信号状态时
2.等待超时
那到底是什么意思呢,别着急,我们再看看参数:
hHandle [in] Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.

If this handle is closed while the wait is still pending, the function's behavior is undefined.

该参数是一个句柄对象,如果句柄已经Close掉后还在WaitForSingleObject那么这种情况是未定义的,未定义是啥意思了就是会有意想不到的效果,
说白了就是重大的隐藏的BUG
dwMilliseconds [in] Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If
dwMilliseconds is zero, the function tests the object's state and returns immediately. If
dwMilliseconds is INFINITE, the function's time-out interval never elapses. 
该参数是指定超时间隔,如果参数为零则函数马上返回,如果参数为INFINITE,函数会一直等待。
另外该函数的返回值有主要有两种状态:
WAIT_OBJECT_0 The state of the specified object is signaled. 表示句柄为有信号状态时候返回
WAIT_TIMEOUT The time-out interval elapsed, and the object's state is nonsignaled. 表示等待超时返回
现在我们去掉主函数的Sleep延时1s的代码,在CreateThread()后面加上一句:
WaitForSingleObject(HOne,INFINITE);

现在我们再看看运行结果:

果然正确,现在明白WaitForSingleObject(HOne,INFINITE);的意思了吧

版权声明:本文为博主原创文章,未经博主允许不得转载。

CreateThread简单那多线程编程的更多相关文章

  1. Linux下简单的多线程编程--线程池的实现

    /* 写在前面的话: 今天刚“开原”,选择了一篇关于线程池的文件与大家分享,希望能对您学习有所帮助,也希望能与大家共同学习! 选择在这个特殊的时候注册并发文章也是有一些我个人特殊的意义的,看我的id( ...

  2. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

  3. 【转】 Linux下的多线程编程

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/12/07/280 ...

  4. Linux下的多线程编程

    1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的 Unix也支持线程的概念,但是在一个进程(proces ...

  5. Linux下多线程编程

    一.为什么要引入线程? 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维 ...

  6. 【转】Linux下的多线程编程

    1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的 Unix也支持线程的概念,但是在一个进程(proces ...

  7. 《转》Linux下的多线程编程

    原地址:http://linux.chinaunix.net/doc/program/2001-08-11/642.shtml 1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程 ...

  8. C#多线程编程的同步也线程安全

    前一篇文章记录了简单的多线程编程的几种方式,但是在实际的项目中,也需要等待多线程执行完成之后再执行的方法,这个就叫做多线程的同步,或者,由于多个线程对同一对象的同时操作造成数据错乱,需要线程安全.这篇 ...

  9. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

随机推荐

  1. Hdu2437-Jerboas(取余数判重搜索)

    Jerboas are small desert-living animals, which resemble mice with a long tufted tail and very long h ...

  2. poj3349(哈希+链地址法)

    给出N个六边形的6个边长,问其中是否有完全相同的两个六边形,完全相同包括边的长度和位置都要相同.边给出的顺序是逆时针或者顺时针的. 给每个6边形一个哈希值,方法是对6条边长度的平方和取模 #inclu ...

  3. 《Java程序员面试笔试宝典》之 什么是AOP

    AOP(Aspect-Oriented Programming,面向切面编程)是对面向对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态地修改模型从而满足新的需求.例如,在不改变原来业务逻 ...

  4. goahead webserver源码分析

    1.一个txt文本架构图 main() | |--websOpenServer() |             |-- websOpenListen() |                       ...

  5. Python 异步IO、IO多路复用

    事件驱动模型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  6. Kafka的Producer以及Consumer远程调用问题

    公司需要分布式的JMS,所以研究了Kafka,之前在本地都没有出现问题,但是在服务器上布Kafka的时候发现了消费者无法消费的问题. kafka布到一台服务器上面,由于业务原因,producer和ka ...

  7. Prototypes analyze(二叉排序树,不同树形个数)

    Prototypes analyze 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 ALpha Ceiling Manufacturers (ACM) is ana ...

  8. arcengine 调用arctoolbox功能的举例 spatialJoin

    废话不多说,code是王道. 其中str1.str2两个参数是target路径.join路径 private void spatialJoin(Geoprocessor gp, string str1 ...

  9. EffectiveC#12,13,14--成员初始化

    1.在一个类里声明变量的同时,直接创建实例值.包括静态的和实例的变量 例:object m_o = new object(); 如下情况时不建议这么做:第一种 值类型. int i=new int() ...

  10. vs2013 JS代码提示

    1.JS提示 在Js文件头部加 /// <reference path="ext-all-dev.js" /> 要求引用的js和本js在同一目录,否则需要全部路径