C/C++ 多线程的学习心得总结

个人觉得在学习多线程编程之前最好先了解进程和线程的关系, 然后在学习线程工作方式的过程中动手写个(我是从抄开始的)多线程的小程序, 会对学习多线程有很大的帮助, 否则只有理论是很抽象的.

在学习多线程编程之前, 必须先知道什么是 线程函数, 线程函数就是另一个线程的入口函数. 默认情况下一个我们所写的代码都是只有一个线程的, 而这个线程的入口函数就是main() 函数, 这是系统默认的. 而我们创建的另一个线程也需要一个函数来进入, 这个函数就叫做线程函数.

在C/C++中, 可以调用 '运行期库' 函数 _beginthreadex(...), 来创建一个线程, _beginthreadex(...)函数接受6个参数, 其中第3个参数要求传入该线程的入口函数的地址(即:传入线程函数的函数名+&即可), 其它的每个参数的意思可以在msdn或网上查一下, 入门的话其余参数全部传0即可.

_beginthreadex(...)函数返回一个句柄, 就是新线程的句柄. 对于传入的线程函数是有要求的, 线程函数必须返回 unsigned __stdcall 类型, 并且接受一个 void* 型参数, 函数的内容就可以自己定了.
先来段多线程的简单代码:


代码如下:

#include<windows.h>
#include<process.h>
#include<iostream>
using namespace std;
bool stop;
unsigned Counter;
unsigned __stdcall thread(void*)
{
cout <<"In second thread..." <<endl;
while (!stop){
Sleep(200);
cout <<Counter++ <<" " <<flush;
}
//_endthreadex(0);
return 0;
}
int main()
{
HANDLE hThread;
unsigned int threadID;
stop = false;
cout <<"Creating second thread..." <<endl;
// Create the second thread.
hThread = (HANDLE)_beginthreadex(NULL, 0, &thread, NULL, 0, &threadID);
// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
//WaitForSingleObject(hThread, INFINITE);
system("pause");
stop = true;
//cin >>stop;
cout <<"Counter is-> " <<Counter <<endl;
// Destroy the thread object.
CloseHandle(hThread);
system("pause");
return 0;
}

代码是正确的, 复制粘贴到 Visual C++ 6.0 中, 即可编译运行. 但是会发现 _beginthreadex(...) 函数未定义的编译错误. 原因是因为我们的visual c++ 6.0 默认的是在单线程模式下编程, 如果需要进行多线程编程, 需要转换一下编译器的 '运行期库' , 方法很简单:
Project --> Settings --> C/C++ 中 选择 Category 中的 Code generation , 然后在 Use run-time library 里面选含有Multithread的其中一个就可以了.
这时再编译, 就可以通过了. 有了这个例子的函数, 现在应该已经入门了吧. 不过除了这个还有很多基础知识要补上, 推荐通读几遍 <windows核心编程(第四版)> 的第6章.
实际上, 在不同的编译环境下, _beginthreadex(...)函数可能会有不同的名称, 但是它们都是对 windows函数 CreateThread(...) 的封装, CreateThread(...)函数用来创建一个新的线程函数, CreateThread(...)函数同样接受6个参数, 在类似 _beginthreadex(...)的函数中对其做了一些安全的处理, 如堆栈内存的申请等. 虽然可以用CreateThread函数来创建一个新的线程, 但是强烈建议使用 _beginthreadex(...)函数, 对于CreateThread 函数在<windows核心编程(第四版)>第6章中有很好的讲解.
当一个线程的任务结束, 要退出时, 有四种方法:
1.线程函数返回(最好使用这种方法);
2.通过调用 _endthreadex()或 ExitThread()函数,线程将自行撤消(最好不要使用这种方法);
3.同一个进程或另一个进程中的线程调用 TerminateThread()函数(应该避免使用这种方法);
4.包含线程的进程终止运行(应该避免使用这种方法).
最好通过其入口函数的返回语句(即:return)来退出线程, 也可以通过调用 C/C++ '运行期库'函数 _endthreadex()函数来退出, 还有两种退出的方法, 都是类似的强制退出. 最好使用线程函数的返回语句(return)来退出线程, 只有这样才能安全的回收该线程的处理器资源和内存资源. 而实际上 _endthreadex()函数和 _beginthreadex(...)函数一样, 是封装了windows函数 ExitThread(), 如果一定要强制退出线程, 那么强烈建议调用 _endthreadex() 函数, 这样能安全的回收系统资源.

具体的 _beginthreadex(...)函数 和 _endthreadex()函数在<windows核心编程(第四版)>第6章中有很好的剖析. 同时还有两个 _beginthread(...) 和 _endthread() 运行期库函数, 也有讲解.
windows还提供了一些库函数用来获得当前进程或者线程的句柄, 如 HANDLE GetCurrentProcess() 函数返回当前进程的句柄, HANDLE GetCurrentThread() 函数返回当前线程的句柄, 但是需要注意的是, 这些句柄都是 '伪句柄' , 即: 只在本进程和本线程内可用, 不可传出取用.

如果需要在外部使用其它线程或进程的句柄, 则可以用 DuplicateHandle(...) 函数获得其它进程或者线程的 '实句柄' , 该函数接受7个参数, 具体的用法可以查阅一下msdn和网络. 需要注意的是, 在使用完 由DuplicateHandle(...) 函数获得的句柄后, 需要使用 CloseHandle() 函数来关闭该句柄.

(0)

相关推荐

  • C++开发:为什么多线程读写shared_ptr要加锁的详细介绍

    我在<Linux 多线程服务端编程:使用 muduo C++ 网络库>第 1.9 节"再论 shared_ptr 的线程安全"中写道: (shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化.根据文档(http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#ThreadSafety), shared_ptr 的线程

  • c语言实现多线程动画程序示例

    该程序是利用opengl图形库与fmod音频库写的一个简单3d动画程序.该程序在vs下运行良好,若缺少相关dll文件请确认已配制fmod与opengl库. mixmodel.cpp 复制代码 代码如下: // mixmodel.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h" //定义一个线程DWORD WINAPI SoundProc( LPVOID LPVIDEOPARAMETERS);//光照变量GLfloat  whiteLight[] =

  • c语言socket多线程编程限制客户端连接数

    先上一些多线程需要使用的函数定义: 复制代码 代码如下: DWORD WINAPI ProcessClientRequests(LPVOID lpParam)  //新线程将会执行的函数定义{      return 0;} HANDLE handler=CreateThread(NULL, 0, ProcessClientRequests, &clientsocket, 0, NULL);   //这里比较简单,&clientsocket是个指针,是从主线程传入新线程的参数 WaitFo

  • c#多线程编程基础

    无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应用户操作,同时在用户事件之间或者甚至在用户事件期间利用处理器,最强大的方式之一是使用多线程技术. 多线程:线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.如果某个线程进行一次长延迟操作, 处理器就切换到另一个线程执行.这样,多个线程的并行(并发)执行隐藏了长延迟,提高了处理器资源利用率

  • C++实现多线程查找文件实例

    主要是多线程的互斥 文件 的查找 多线程互斥的框架 复制代码 代码如下: //线程函数  UINT FinderEntry(LPVOID lpParam)  {      //CRapidFinder通过参数传递进来       CRapidFinder* pFinder = (CRapidFinder*)lpParam;      CDirectoryNode* pNode = NULL;      BOOL bActive = TRUE; //bActive为TRUE,表示当前线程激活   

  • c#多线程的应用全面解析

    1.使用多线程的几种方式 (1)不需要传递参数,也不需要返回参数 ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值. 复制代码 代码如下: class Program { static void Main(string[] args) { for (int i = 0; i < 30; i++) { ThreadStart threadStart = new ThreadStart(Calculate); Thread thread = n

  • C#中的多线程多参数传递详解

    之前做了一个小的应用程序,用的是c#语言,涉及到了多线程的多参数传递,经过查找资料总结了一下解决方案! 第一种解决方案的原理是:将线程执行的方法和参数都封装到一个类里面.通过实例化该类,方法就可以调用属性来实现间接的类型安全地传递多个参数.看如下代码: 复制代码 代码如下: using System;using System.Threading; //ThreadWithState 类里包含了将要执行的任务以及执行任务的方法public class ThreadWithState {//要用到的

  • C#简单多线程同步和优先权用法实例

    本文实例讲述了C#简单多线程同步和优先权用法.分享给大家供大家参考.具体分析如下: 本文实例题目如下: 麦当劳有两个做汉堡的厨师(工号:11,12)和三个销售人员(工号:21,22,23). 厨师生产汉堡,并负责将做好的汉堡放入货架,货架台大小有限,最多放6个汉堡,11和12不能同时往货架台上放汉堡,11具有优先权. 销售人员负责销售食品,三个销售人员取食品时,货架不能为空,三人不能同时取,23优先权最高,21最低.21卖的最快,取得频率最高,22次之. 一天的工作量是销售70个汉堡. 这里先来

  • c语言多线程编程使用示例

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <pthread.h> #define THREAD_NUM 10 void *test(void *args) { printf("tid %d: i say 'Hello'.\n", args); return NULL;} int main() { int i, err; pthread_t child[THREAD_NUM]; f

  • VC多线程编程详解

    本文实例讲述了VC多线程编程概念与技巧,分享给大家供大家参考.具体分析如下: 一.多线程编程要点 线程是进程的一条执行路径,它包含独立的堆栈和CPU寄存器状态,每个线程共享所有的进程资源,包括打开的文件.信号标识及动态分配的内存等.一个进程内的所有线程使用同一个地址空间,而这些线程的执行由系统调度程序控制,调度程序决定哪个线程可执行以及什么时候执行线程.线程有优先级别,优先权较低的线程必须等到优先权较高的线程执行完后再执行.在多处理器的机器上,调度程序可将多个线程放到不同的处理器上去运行,这样可

  • VC++中进程与多进程管理的方法详解

    本文实例讲述了VC++中进程与多进程管理的方法,分享给大家供大家参考.具体方法分析如下: 摘要: 本文主要介绍了多任务管理中的多进程管理技术,对进程的互斥运行.子进程的创建与结束等作了较详细的阐述. 关键词: VC++6.0:进程:环境变量:子进程 进程 进程是当前操作系统下一个被加载到内存的.正在运行的应用程序的实例.每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而地址空间则包括了所有程序模块的代码和数据以及线程堆栈.堆分

随机推荐