一、线程基本概念线程是在进程中产生的一个执行单元是CPU调度和分配的最小单元其在同一个进程中与其他线程并行运行他们可以共享进程内的资源比如内存、地址空间、打开的文件等等。线程是CPU调度和分派的基本单位进程是分配资源的基本单位进程正在运行的程序是处于执行期的程序以及它所管理的资源如打开的文件、挂起的信号、进程状态、地址空间等等的总称从操作系统核心角度来说进程是操作系统调度除CPU时间片外进行的资源分配和保护的基本单位它有一个独立的虚拟地址空间用来容纳进程映像(如与进程关联的程序与数据)并以进程为单位对各种资源实施保护如受保护地访问处理器、文件、外部设备及其他进程(进程间通信)计算机有很多资源组成比如CPU、内存、磁盘、鼠标、键盘等就像一个工厂由电力系统、作业车间、仓库、管理办公室和工人组成假定工厂的电力有限一次只能供给一个或少量几个车间使用。也就是说一部分车间开工的时候其他车间都必须停工。背后的含义就是单个CPU一次只能运行一个任务多个CPU能够运行少量任务。线程就好比车间里的工人。一个进程可以包括多个线程他们协同完成某一个任务。二、为什么使用多线程1.避免阻塞大家知道单个进程只有一个主线程当主线程阻塞的时候整个进程也就阻塞了无法再去做其它的一些功能了。2.避免CPU空转应用程序经常会涉及到RPC数据库访问磁盘IO等操作这些操作的速度比CPU慢很多而在等待这些响应时CPU却不能去处理新的请求导致这种单线程的应用程序性能很差。3.提升效率一个进程要独立拥有4GB的虚拟地址空间而多个线程可以共享同一地址空间线程的切换比进程的切换要快得多。上下文切换三、创建线程函数1.CreateThreadCreateThread是一种微软在Windows API中提供了建立新的线程的函数该函数在主线程的基础上创建一个新线程。线程终止运行后线程对象仍然在系统中必须通过CloseHandle函数来关闭该线程对象。12345678HANDLECreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,//SDSIZE_TdwStackSize,//initialstacksizeLPTHREAD_START_ROUTINE lpStartAddress,//threadfunctionLPVOIDlpParameter,//threadargumentDWORDdwCreationFlags,//creationoptionLPDWORDlpThreadId//threadidentifier)第一个参数 lpThreadAttributes 表示线程内核对象的安全属性一般传入NULL表示使用默认设置。第二个参数 dwStackSize 表示线程栈空间大小。传入0表示使用默认大小1MB。第三个参数 lpStartAddress 表示新线程所执行的线程函数地址多个线程可以使用同一个函数地址。第四个参数 lpParameter 是传给线程函数的参数。第五个参数 dwCreationFlags 指定额外的标志来控制线程的创建为0表示线程创建之后立即就可以进行调度如果为CREATE_SUSPENDED则表示线程创建后暂停运行这样它就无法调度直到调用ResumeThread()。第六个参数 lpThreadId 将返回线程的ID号传入NULL表示不需要返回该线程ID号2._beginthreadex123456789unsignedlong_beginthreadex(void*security,// 安全属性 为NULL时表示默认安全性unsigned stack_size,// 线程的堆栈大小 一般默认为0unsigned(_stdcall *start_address)(void*),// 线程函数void*argilist,// 线程函数的参数unsigned initflag,// 新线程的初始状态0表示立即执行//CREATE_SUSPENDED表示创建之后挂起unsigned *threaddr// 用来接收线程ID);返回值 : // 成功返回新线程句柄 失败返回0__stdcall表示1.参数从右向左压入堆栈2.函数被调用者修改堆栈四、简单多线程示例现在有三个任务Tom每隔3秒捉一次JerryJerry每隔2秒吃一次奶酪Spike每隔1秒打一次Tom。分别用CreateThread和_beginthreadex实现使用_beginthreadex12345678910111213141516171819202122232425262728293031323334353637383940414243#includestdio.h#includeWindows.h#includeprocess.h//Tom每隔3秒捉一次老鼠unsigned WINAPI thread_main_Tom(void* arg) {intcnt *((int*)arg);for(inti 0; i cnt; i) {Sleep(3000);puts(Tom 捉老鼠\n);}return0;}//Jerry每隔1秒吃一次奶酪unsigned WINAPI thread_main_Jerry(void* arg) {intcnt *((int*)arg);for(inti 0; i cnt; i) {Sleep(1000);puts(Jerry 吃奶酪\n);}return0;}//Spike每隔2秒打一次猫unsigned WINAPI thread_main_Spike(void* arg) {intcnt *((int*)arg);for(inti 0; i cnt; i) {Sleep(2000);puts(Spike 打猫\n);}return0;}intmain() {intTom 20, Jerry 50, Spike 40;//保存线程IdunsignedintTom_id, Jerry_id, Spike_id;//创建线程_beginthreadex(NULL, 0, thread_main_Tom, (void*)Tom, 0, Tom_id);_beginthreadex(NULL, 0, thread_main_Jerry, (void*)Jerry, 0, Jerry_id);_beginthreadex(NULL, 0, thread_main_Spike, (void*)Spike, 0, Spike_id);system(pause);return0;}运行结果使用CreateThread1234567891011121314151617181920212223242526#includestdio.h#includeWindows.h#includeprocess.h//DWORD就是unsigned long//LPVOID是void*DWORD_stdcall ThreadFun(LPVOIDp) {printf(我是子线程PID%d, GetCurrentThreadId());return0;}intmain() {printf(main begin\n);HANDLEhThead;DWORDdwThreadID;hThead CreateThread(NULL, 0, ThreadFun, 0, 0, dwThreadID);printf(我是主线程PID%d\n,GetCurrentThreadId());Sleep(2000);//关闭线程if(hThead) {CloseHandle(hThead);}system(pause);return0;}运行结果到此这篇关于C/C中线程基本概念与创建详解的文章就介绍到这了