多线程学习----CreateThread

Posted 神秘的探索者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程学习----CreateThread相关的知识,希望对你有一定的参考价值。

tt.cpp : 定义控制台应用程序的入口点。

 同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等,但是同一个进程中的多个线程都有各自的调用栈、寄存器环境和线程本地存储。

线程都拥有自己的堆栈,临界区等主要是控制访问全局变量和成员变量

  1 #include "stdafx.h"
  2 #include <Windows.h>
  3 #include <stdio.h>
  4 #include <conio.h>
  5 
  6 #define WM_NIHAO  1001
  7 #define THREADNUM 3
  8 
  9 /*
 10 volatile 修饰符的作用是告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。
 11 对于多线程引用的全局变量来说,volatile 是一个非常重要的修饰符。
 12 */
 13 volatile int            gInt=0;
 14 //普通临界区
 15 static CRITICAL_SECTION cs;
 16 //MFC临界区
 17 //CCriticalSection        ccs;
 18 
 19 //使用原子操作的方法
 20 volatile LONG aomic=100;
 21 
 22 void fun(int tNum)
 23 {
 24     //printf("第%d线程已经工作了\n",tNum);
 25 
 26     if (1)
 27     {
 28         //临界区
 29         EnterCriticalSection(&cs);// 进入临界区,其它线程则无法进入
 30         //ccs.Lock();
 31         // 安全访问该区域  
 32         gInt--;
 33         printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
 34         Sleep(0);//致使不使用临界区肯定出错的方法
 35         gInt++;
 36         printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
 37         //ccs.Unlock();
 38         LeaveCriticalSection(&cs);  // 离开临界区,其它线程可以进入 
 39 
 40         //原子操作
 41         InterlockedIncrement(&aomic);
 42         InterlockedDecrement(&aomic);
 43     }
 44 
 45     MSG   msg;   
 46     //GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。
 47     //GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
 48     //返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。
 49     while(1)
 50     {   
 51         int tGM=::GetMessage(&msg,NULL,0,0);
 52         switch(msg.message)   
 53         {   
 54         case WM_NIHAO:   
 55             printf("第%d线程接收到主线程的发过来的消息:%s\n",tNum,(char*)msg.wParam);
 56                 break;
 57         default:
 58             break;
 59         } 
 60 
 61         //不需要接收第二次消息
 62         if (tGM>0)
 63         {
 64             break;
 65         }
 66     }
 67 
 68     printf("%d线程结束",tNum);
 69 
 70     //该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
 71     //ExitThread(1);
 72 }
 73 int _tmain(int argc, _TCHAR* argv[])
 74 {
 75     // 在进入多线程环境之前,初始化临界区  
 76     InitializeCriticalSection(&cs);  
 77 
 78     DWORD threadId[THREADNUM];
 79     HANDLE hThread[THREADNUM];
 80     for (int i=0;i<THREADNUM;i++)
 81     {
 82         hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
 83     }
 84 
 85     while (getch()!=1)
 86     {
 87         Sleep(100);
 88     }
 89     //试探线程读取全局变量
 90     gInt=100;
 91     for (int i=0;i<THREADNUM;i++)
 92     {
 93         if (-1==ResumeThread(hThread[i]))
 94         {
 95             printf("ResumeThread时候出错了\n");
 96             return -1;
 97         }
 98         
 99     }
100     //ResumeThread线程之后线程投入工作需要一定时间
101     Sleep(1000);
102 
103     char buff[20]="ni hao ma?";
104     for (int i=0;i<THREADNUM;i++)
105     {
106         BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
107     }
108     //参数一:线程句柄
109     //参数二:等待时间(毫秒),IGNORE:不等,INFINITE:死等
110     //返回值: WAIT_OBJECT_0: 线程结束
111     //           WAIT_TIMEOUT:超过等待时间,指定的对象处于无信号状态
112     //           WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll为TRUE,则返回值表明所有指定对象的状态是触发的,并且至少对象之一,是一个废弃的互斥对象。
113     //         WAIT_FAILED:出现错误,一般是线程句柄错误
114     //WaitForSingleObject函数,此函数的作用是监视hHandle的状态,当监视的句柄为有信号状态时,即此对象为空闲状态时,此函数返回,才能执行其后的代码。
115     //WaitForSingleObject(hThread,INFINITE);
116 
117     Sleep(1000);
118     //值得注意的是hThread数组的所有成员必须全部有效,有一个没效的话,次函数就会执行失败
119     DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
120     //若果第三个参数是true,则返回值代表所有线程的状态
121     //若果第三个参数是false,则返回值代表那个有返回线程的状态
122     switch (wm)
123     {
124     case WAIT_FAILED:
125         printf("wm-->WAIT_FAILED\n");
126         break;
127     case WAIT_TIMEOUT:
128         printf("wm-->WAIT_TIMEOUT\n");
129         break;
130 
131     case WAIT_ABANDONED_0+0:
132     case WAIT_ABANDONED_0+1:
133     case WAIT_ABANDONED_0+2:
134         printf("wm-->WAIT_ABANDONED_0\n");
135         break;
136 
137     case WAIT_OBJECT_0+0:
138     case WAIT_OBJECT_0+1:
139     case WAIT_OBJECT_0+2:
140         printf("wm-->WAIT_OBJECT_0\n");
141         break;
142 
143     default:
144         break;
145     }
146 
147     //一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。
148     for (int i=0;i<THREADNUM;i++)
149     {
150         TerminateThread(hThread[i],0);
151     }
152 
153     // 释放临界区资源,当不再使用临界区时调用该函数  
154     DeleteCriticalSection(&cs);  
155     return 0;
156 }

 

以上是关于多线程学习----CreateThread的主要内容,如果未能解决你的问题,请参考以下文章

C语言怎么写线程代码

秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别

windows多线程 创建线程 CreateThread

秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别

多线程编程 CreateThread(解释了TContext)

线程学习知识点总结