多线程编程1-入门

常用的多线程API函数(转自http://blog.csdn.net/hcqi2004/article/details/3534853)

CreateThread函数:

HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes,

  DWORD dwStackSize,

  LPTHREAD_START_ROUTINE lpStartAddress,

  LPVOID lpParameter,

  DWORD dwCreationFlags,

  LPDWORD lpThreadId);

参数

lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。

dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。

lpStartAddress,指向线程函数的指针,形式:@函数名,格式不正确将无法调用成功。

线程函数的格式:DWORD  WINAPI Threadfnc(LPVOID N); 说明:返回值必须为DWORD,必须使用WINAPI,函数名称Threadfnc可以自己随便命名,函数的参数必须是LPVOID类型。

lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。

dwCreationFlags :线程标志,可取值如下 
  CREATE_SUSPENDED 创建一个挂起的线程; 
  0 创建后立即激活。

lpThreadId:保存新线程的id。线程id是一个全局变量,唯一的表示系统任一进程中的某个线程。但不能根据id获得其handle。

返回值:

函数成功,返回线程句柄;函数失败返回false。

函数说明:

创建一个线程。

一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的System单元中定义的 BeginTheard函数,因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。

CloseHandle函数

BOOL  CloseHandle(

HANDLE    hObject

);

参数

hObject : 代表一个已打开对象handle

返回值

TRUE:执行成功,

FALSE:执行失败,可以调用GetLastError()获知失败原因。

函数说明:

关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

  若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。

GetExitCodeThread函数:

功能: 获取一个结束线程的返回值

BOOL   GetExitCodeThread (

HANDLE  hThread,

LPDWORD  lpExitCode

);

参数:

hThread: 线程对象的句柄

lpExitCode: 用于存储线程的返回值,如果线程结束,那么线程的结束代码会被放在lpExitCode参数中;如果线程尚未结束,lpExitCode的值是STILL_ACTIVE.

返回值:

函数执行成功则返回非0值,否则返回 0(FALSE)。

函数说明:

获取线程结束的返回值。

ExitThread 函数

VOID ExitThread(DWORD dwExitCode);

参数

dwExitCode: 线程的结束代码

返回值

  无返回值.

说明

该函数最好用于 C 程序里,在 C++里,return 前会调用析构函数,调用该函数结束线程,并不会调用有关对象的析构函数以及其它的自动清理动作.当在线程里调用该函数后,线程的堆栈将被收回,所有未完成的I/O操作将被取消,于其连接的动态连接库也被分离.

当调用线程的函数返回后,线程自动终止。如果需要在线程的执行过程中终止则可调用该函数。

WaitForSingleObject函数

DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

);

参数

hHandle:事件的句柄,在此指线程句柄;

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

函数说明:

设即将等待的线程为线程#1,正在执行的线程为线程#2,调用WaitForSingleObject,设定该函数的第一个参数是线程#2的句柄,则线程#1开始睡眠,直到线程#2结束为止。

创建多个线程,线程并不一定是按照创建的先后顺序结束的。调用该函数只能监测指定的一个线程。

WaitForMultipleObject函数

DWORD WaitForMultipleObjects(

  DWORD nCount,

  const HANDLE* lpHandles,

  BOOL bWaitAll,

  DWORD dwMilliseconds

  );

参数

nCount:表示lpHandles所指句柄数据的元素个数,

最大容量是MAXIMUM_WAIT_OBJECTS

lpHandles:指向对象句柄数组的指针

bWaitAll:是否等待所有对象都有信号

此值为false,返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被出发,这个函数返回的只是其中序号最小的那个。

此值为true,

返回值为WAIT_OBJECT_0,表示所有的事件都被设置了   .

返回值为WAIT_ABANDONED_0到(WAIT_ABANDONED_0+ nCount–1) ,表示有一个事件被丢弃

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果在规定那个时间内有信号状态则返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

函数说明:

多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将的不到被出理的机会。

lpHandles数组中不允许有缝隙产生,当某个handle被激发了,你应该在下一次调用WaitForMultipleObjects函数之前将该handle从lpHandles数组中移除。

Windows消息循环

Windows程序中的标准消息循环看起来想这个样子:

while( GetMessage(&Msg,NULL,0,0) )

{

TranslateMessage(&Msg);

DispatchMessage(&Msg);

}

调用getMessage(),除非有一个消息真正进入消息列队中,否则它不会返回。在此期间,Windows就可以自由的将cpu时间给予其他程序。

常常回到主消息循环是十分重要的事,如果你没有这么做,你的窗口就会停止重绘,就会出现一些用户不喜欢的事情。在你使用WaitForSingleObject或者WaitForMultipleObjects函数时,它在等待某个对象被激发时,你根本没有办法回到主消息循环中去。

为了解决这个问题,主消息循环必须修改,使它可以同时等待消息或者是核心对象被激发,你必须使用MsgWaitForMultipleObjects函数。

MsgWaitForMultipleObjects函数

DWORD   MsgWaitForMultipleObjects ( 
   DWORD   nCount, 
   LPHANDLE   pHandles, 
   BOOL  fWaitAll, 
   DWORD  dwMilliseconds, 
   DWORD  dwWakeMask 
);

参数

nCount:列表中的句柄数量

pHandles:指向对象句柄数组的指针

fWaitAll:是否等待所有对象都有信号,

dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;

此值为0,代表立刻返回

此值为INFINITE,代表无穷等待。

dwWakeMask :指定哪些消息是观察对象(欲观察的用户输入消息),可以是:

QS_ALLINPUT

QS_HOTKEY

QS_INPUT

QS_KEY

QS_MOUSE

QS_MOUSEBUTTON

QS_MOUSEMOVE

QS_PAINT

QS_POSTMESSAGE

QS_SENDMESSAGE

QS_TIMER

返回值

WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态

WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息

WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态

WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex

  WAIT_TO_COMPLETION:(仅适用于WaitForSingleObjectEx),由于一个I/O完成操作已准备好执行,从而造成了函数的返回。

  WAIT_OBJECT_0 + nCount:接受到由dwWakeMask指定的消息

函数说明:

迭代等待指定线程中的特定消息,其实这个函数就是专为等待消息而定义的。

MsgWaitForMultipleObjects函数不允许句柄数组中有缝隙产生,所以当某个句柄被激发了,你应该在下一次调用MsgWaitForMultipleObjects之前先把句柄数组做个整理、压缩

TerminateThread函数

BOOL TerminateThread(

HANDLE  hThread,

DWORD  dwExitCode

);
参数

hThread:线程的句柄

dwExitCode:线程的结束代码

返回值

True:函数成功

False:函数失败

函数说明:

如果在线程的外面终止线程,则可调用该函数。该函数执行后,线程handle将变成激发状态,并且传回结束代码。

TerminateThread函数是一个危险的函数,应该最不得已的情况下才使用。此函数一旦成功执行,指定的线程会立刻终止执行,那么可能有很多的结束处理工作还没来得及进行,线程的堆栈没有被释放,于是可能会引起内存泄漏- - -,但是此线程加载的DLL也没有机会被通知结束执行。

SuspendThread函数

DWORD  SuspendThread(

HANDLE hThread   //线程的句柄

);

返回值

函数成功,返回线程的前一个暂停计数或者说是前一个挂起次数,否则返回0x FFFFFFFF

函数说明:

挂起线程。一个线程可以被挂起多次。如果一个线程被挂起n次,则该线程也必须被恢复n次才可能得以执行。。

ResumeThread函数

DWORD  ResumeThread(

HANDLE hThread  //线程的句柄

);

返回值

函数成功,返回线程目前的挂起次数,否则返回0x FFFFFFFF

函数说明:

唤醒线程。

句柄,是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows使用了大量的句柄来标识很多对象。

Sleep函数编辑

函数名: Sleep

功 能: 执行挂起一段时间

用 法: void Sleep(DWORD dwMilliseconds);

在VC中使用带上头文件

#include <windows.h>

( Sleep函数存放头文件:WinBase.h)

在gcc编译器中,使用的头文件因gcc版本的不同而不同

#include <unistd.h>

Sleep()单位为毫秒,sleep()单位为秒(如果需要更精确可以用usleep单位为微秒)

返回值

若进程/线程挂起到参数所指定的时间则返回0,若有信号中断则返回剩余秒数。

下面创建一个简单的线程例子

#include<iostream>
#include<Windows.h>
using namespace std;

//线程函数
DWORD WINAPI Fun1proc(
	LPVOID lpparameter//向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL
);

//main函数为主线程的入口函数地址
void main()
{
	HANDLE hThread1;
	hThread1=CreateThread(NULL//第一个参数为NULL,设置为默认的安全性
		                  ,0//第二个参数让新线程与调用线程采用一样的栈大小
						  ,Fun1proc//第三个参数指定线程1的入口函数地址
						  ,NULL//第四个参数是传递给线程1的参数
						  ,0//第五个参数设置为0让线程一旦创建就立即执行
						  ,NULL//第六个参数新线程的ID
						  );
	CloseHandle(hThread1);//关闭新线程的句柄(这里没有终止创建的新线程,只是说主线程对它的引用不感兴趣)

	cout<<"main thread is running"<<endl;
	Sleep(5000);
	//system("pause");
}

//线程1的入口函数
DWORD WINAPI Fun1proc( LPVOID lpparameter)
{
	cout<<"thread1 is running!!!"<<endl;
	return 0;
}

  

时间: 2024-07-28 15:55:40

多线程编程1-入门的相关文章

多线程编程 之 入门篇

<pre name="code" class="cpp">自己第一次涉及c语言的多线程编程,实属入门了解级别的:之前只做过java的Runnable的多线程编程.本次我们可以把屏幕看成是一个资源,这个资源被两个线程所共用, /* #include <iostream> #include <windows.h> using namespace std; DWORD WINAPI Fun(LPVOID lpParamter) { wh

java多线程编程从入门到卓越(超详细总结)

导读:java多线程编程不太熟?或是听说过?或是想复习一下?找不到好的文章?别担心我给你们又安利一波,文章内容很全,并且考虑到很多开发中遇到的问题和解决方案.循环渐进,通俗易懂,文章较长,建议收藏再看! 往期精彩放送:一文搞定Java的输入输出流等常见流 一文搞定Java集合类,你还在为Java集合类而烦恼吗? 文章目录 1.多线程的概念 2.多线程并发 3.多线程程序设计 继承Thread类创建线程 新建类实现Runnable接口创建线程 改进(匿名内部类方式) 获取线程的名字和当前线程对象

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一

C++多线程编程入门之经典实例

多线程在编程中有相当重要的地位,我们在实际开发时或者找工作面试时总能遇到多线程的问题,对多线程的理解程度从一个侧面反映了程序员的编程水平. 其实C++语言本身并没有提供多线程机制,但Windows系统为我们提供了相关API,我们可以使用它们来进行多线程编程.本文就以实例的形式讲解多线程编程的知识. 创建线程的API函数 C++代码 HANDLE CreateThread( __in   SEC_ATTRS SecurityAttributes, __in   ULONG StackSize,  

socket 网络编程快速入门(二)教你编写基于UDP/TCP的服务端多线程通信

在上一篇博文中,我们介绍了利用socket进行简单的UDP/TCP的服务端和客户端的通信. (一) 在基于UDP的程序中,你有没有想过,如果我的这台主机在通讯的时候要求既能够收到别的主机发来的数据,又能够自己向目的主机发出数据,该怎样实现?也就是说需要两个while循环同时进行.答案是使用多线程,一个线程用于接受数据,另一个线程用来发送数据.接下来我们介绍WinSock的多线程编程. 多线程的实现我们使用_beginthread()函数: uintptr_t _beginthread( void

深入 HTML5 Web Worker 应用实践:多线程编程

深入 HTML5 Web Worker 应用实践:多线程编程 HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越多崭新的特性和功能.它不但强化了 Web 系统或网页的表现性能,而且还增加了对本地数据库等 Web 应用功能的支持.其中,最重要的一个便是对多线程的支持.在 HTML5 中提出了工作线程(Web Worker)的概念,并且规范出 Web Worker 的三大主要特征:能够长时间运行(响应),理想的启

浅析C++多线程编程理论与实践

写这篇博客之前,由于对多线程也不是很了解,一直觉得多线程是个很神奇的东西,但项目中又需要用到,所以借此机会学习了一下,也算做个入门总结吧,写下来总是好的!言归正传,首先介绍几个多线程相关的基本概念: 并发.并行.同步.异步.多线程的区别 1.并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.其中两种并发关系分别是同步和互斥. 2.并行:在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特征:在多处理器系统中,进程

Python黑客编程2 入门demo--zip暴力破解

Python黑客编程2 入门demo--zip暴力破解 上一篇文章,我们在Kali Linux中搭建了基本的Python开发环境,本篇文章为了拉近Python和大家的距离,我们写一个暴力破解zip包密码的小程序.这个例子来自于<Voilent Python>一书,这也是一本python黑客编程的入门书,推荐大家看一看. 照顾没有接触过Python编程的同学,行文可能会有些啰嗦. 废话少说,我们进入正题. 2.1 准备基本材料 在/home/ziptest/目录下,我创建了两个文件,一个test

delphi之多线程编程(尚未学习)

本文的内容取自网络,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过,所以仅仅是看上去会一些,明白了2+2的时候,其实我还不知道1+1. 开始本应该是一篇洋洋洒洒的文字, 不过我还是提倡先做起来, 在尝试中去理解.先试试这个:  procedure TForm1.Button1Click(Sender: TObject); var   i: Integer; begin 

Linux多线程编程小结

 Linux多线程编程小结 前一段时间由于开题的事情一直耽搁了我搞Linux的进度,搞的我之前学的东西都遗忘了,非常烦躁的说,如今抽个时间把之前所学的做个小节.文章内容主要总结于<Linux程序设计第3版>. 1.Linux进程与线程 Linux进程创建一个新线程时,线程将拥有自己的栈(由于线程有自己的局部变量),但与它的创建者共享全局变量.文件描写叙述符.信号句柄和当前文件夹状态. Linux通过fork创建子进程与创建线程之间是有差别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的