多线程学习(一)----CreateThread
来源:互联网 发布:淘宝服装简介怎么写 编辑:程序博客网 时间:2024/05/16 23:39
// tt.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#define WM_NIHAO 1001
#define THREADNUM 3
/*
volatile 修饰符的作用是告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。
对于多线程引用的全局变量来说,volatile 是一个非常重要的修饰符。
*/
volatile int gInt=0;
//普通临界区
static CRITICAL_SECTION cs;
//MFC临界区
//CCriticalSection ccs;
//使用原子操作的方法
volatile LONG aomic=100;
void fun(int tNum)
{
//printf("第%d线程已经工作了\n",tNum);
if (1)
{
//临界区
EnterCriticalSection(&cs);// 进入临界区,其它线程则无法进入
//ccs.Lock();
// 安全访问该区域
gInt--;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
Sleep(0);//致使不使用临界区肯定出错的方法
gInt++;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
//ccs.Unlock();
LeaveCriticalSection(&cs); // 离开临界区,其它线程可以进入
//原子操作
InterlockedIncrement(&aomic);
InterlockedDecrement(&aomic);
}
MSG msg;
//GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。
//GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
//返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。
while(1)
{
int tGM=::GetMessage(&msg,NULL,0,0);
switch(msg.message)
{
case WM_NIHAO:
printf("第%d线程接收到主线程的发过来的消息:%s\n",tNum,(char*)msg.wParam);
break;
default:
break;
}
//不需要接收第二次消息
if (tGM>0)
{
break;
}
}
printf("%d线程结束",tNum);
//该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
//ExitThread(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
// 在进入多线程环境之前,初始化临界区
InitializeCriticalSection(&cs);
DWORD threadId[THREADNUM];
HANDLE hThread[THREADNUM];
for (int i=0;i<THREADNUM;i++)
{
hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
}
while (getch()!='1')
{
Sleep(100);
}
//试探线程读取全局变量
gInt=100;
for (int i=0;i<THREADNUM;i++)
{
if (-1==ResumeThread(hThread[i]))
{
printf("ResumeThread时候出错了\n");
return -1;
}
}
//ResumeThread线程之后线程投入工作需要一定时间
Sleep(1000);
char buff[20]="ni hao ma?";
for (int i=0;i<THREADNUM;i++)
{
BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
}
//参数一:线程句柄
//参数二:等待时间(毫秒),IGNORE:不等,INFINITE:死等
//返回值: WAIT_OBJECT_0: 线程结束
// WAIT_TIMEOUT:超过等待时间,指定的对象处于无信号状态
// WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll为TRUE,则返回值表明所有指定对象的状态是触发的,并且至少对象之一,是一个废弃的互斥对象。
Sleep(1000);
//值得注意的是hThread数组的所有成员必须全部有效,有一个没效的话,次函数就会执行失败
DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
//若果第三个参数是true,则返回值代表所有线程的状态
//若果第三个参数是false,则返回值代表那个有返回线程的状态
switch (wm)
{
case WAIT_FAILED:
printf("wm-->WAIT_FAILED\n");
break;
case WAIT_TIMEOUT:
printf("wm-->WAIT_TIMEOUT\n");
break;
case WAIT_ABANDONED_0+0:
case WAIT_ABANDONED_0+1:
case WAIT_ABANDONED_0+2:
printf("wm-->WAIT_ABANDONED_0\n");
break;
case WAIT_OBJECT_0+0:
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
printf("wm-->WAIT_OBJECT_0\n");
break;
default:
break;
}
//一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。
for (int i=0;i<THREADNUM;i++)
{
TerminateThread(hThread[i],0);
}
// 释放临界区资源,当不再使用临界区时调用该函数
DeleteCriticalSection(&cs);
return 0;
}
//同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等,但是同一个进程中的多个线程都有各自的调用栈、寄存器环境和线程本地存储。
//线程都拥有自己的堆栈,临界区等主要是控制访问全局变量和成员变量
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#define WM_NIHAO 1001
#define THREADNUM 3
/*
volatile 修饰符的作用是告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。
对于多线程引用的全局变量来说,volatile 是一个非常重要的修饰符。
*/
volatile int gInt=0;
//普通临界区
static CRITICAL_SECTION cs;
//MFC临界区
//CCriticalSection ccs;
//使用原子操作的方法
volatile LONG aomic=100;
void fun(int tNum)
{
//printf("第%d线程已经工作了\n",tNum);
if (1)
{
//临界区
EnterCriticalSection(&cs);// 进入临界区,其它线程则无法进入
//ccs.Lock();
// 安全访问该区域
gInt--;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
Sleep(0);//致使不使用临界区肯定出错的方法
gInt++;
printf("第%d线程检测到全局变量gInt的值是:%d\n",tNum,gInt);
//ccs.Unlock();
LeaveCriticalSection(&cs); // 离开临界区,其它线程可以进入
//原子操作
InterlockedIncrement(&aomic);
InterlockedDecrement(&aomic);
}
MSG msg;
//GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。
//GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
//返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。
while(1)
{
int tGM=::GetMessage(&msg,NULL,0,0);
switch(msg.message)
{
case WM_NIHAO:
printf("第%d线程接收到主线程的发过来的消息:%s\n",tNum,(char*)msg.wParam);
break;
default:
break;
}
//不需要接收第二次消息
if (tGM>0)
{
break;
}
}
printf("%d线程结束",tNum);
//该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
//ExitThread(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
// 在进入多线程环境之前,初始化临界区
InitializeCriticalSection(&cs);
DWORD threadId[THREADNUM];
HANDLE hThread[THREADNUM];
for (int i=0;i<THREADNUM;i++)
{
hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fun,(LPVOID)i,CREATE_SUSPENDED,&(threadId[i]));
}
while (getch()!='1')
{
Sleep(100);
}
//试探线程读取全局变量
gInt=100;
for (int i=0;i<THREADNUM;i++)
{
if (-1==ResumeThread(hThread[i]))
{
printf("ResumeThread时候出错了\n");
return -1;
}
}
//ResumeThread线程之后线程投入工作需要一定时间
Sleep(1000);
char buff[20]="ni hao ma?";
for (int i=0;i<THREADNUM;i++)
{
BOOL bPostMes=PostThreadMessage(threadId[i],WM_NIHAO,(WPARAM)buff,(LPARAM)strlen(buff));
}
//参数一:线程句柄
//参数二:等待时间(毫秒),IGNORE:不等,INFINITE:死等
//返回值: WAIT_OBJECT_0: 线程结束
// WAIT_TIMEOUT:超过等待时间,指定的对象处于无信号状态
// WAIT_ABANDONED:WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll为TRUE,则返回值表明所有指定对象的状态是触发的,并且至少对象之一,是一个废弃的互斥对象。
// WAIT_FAILED:出现错误,一般是线程句柄错误
//WaitForSingleObject函数,此函数的作用是监视hHandle的状态,当监视的句柄为有信号状态时,即此对象为空闲状态时,此函数返回,才能执行其后的代码。
//WaitForSingleObject(hThread,INFINITE);Sleep(1000);
//值得注意的是hThread数组的所有成员必须全部有效,有一个没效的话,次函数就会执行失败
DWORD wm=WaitForMultipleObjects(THREADNUM,hThread,true,10000);
//若果第三个参数是true,则返回值代表所有线程的状态
//若果第三个参数是false,则返回值代表那个有返回线程的状态
switch (wm)
{
case WAIT_FAILED:
printf("wm-->WAIT_FAILED\n");
break;
case WAIT_TIMEOUT:
printf("wm-->WAIT_TIMEOUT\n");
break;
case WAIT_ABANDONED_0+0:
case WAIT_ABANDONED_0+1:
case WAIT_ABANDONED_0+2:
printf("wm-->WAIT_ABANDONED_0\n");
break;
case WAIT_OBJECT_0+0:
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
printf("wm-->WAIT_OBJECT_0\n");
break;
default:
break;
}
//一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。
for (int i=0;i<THREADNUM;i++)
{
TerminateThread(hThread[i],0);
}
// 释放临界区资源,当不再使用临界区时调用该函数
DeleteCriticalSection(&cs);
return 0;
}
0 0
- 多线程学习(一)----CreateThread
- Windows多线程学习(一)CreateThread与_beginthreadex
- 多线程编程(一)——CreateThread
- 多线程入门(一CreateThread与_beginthreadex)
- VC++6.0&&VS2008&MFC&API学习问题总结(一)(多线程CreateThread及小问题汇总)
- VC++6.0&&VS2008&MFC&API学习问题总结(一)(多线程CreateThread及小问题汇总) .
- 多线程编程一---CreateThread透析
- C++多线程系列(一)CreateThread和_beginthreadex区别
- 一步一步学习多线程编程之CreateThread
- 多线程CreateThread
- 多线程篇(一)——线程的创建方法CreateThread和_beginthreadex
- (C++多线程问题)CreateThread(…
- (C++多线程问题)CreateThread(…
- WIN32多线程编程( CreateThread 版本)
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 多线程学习(一)
- 修改Eclipse为黑色主题
- 第十周项目1-程序填充与阅读(二)
- [Android] 给图像添加相框、圆形圆角显示图片、图像合成知识
- vs2010 debug afxwin1.inl错误
- UVA Firetruck (DFS)
- 多线程学习(一)----CreateThread
- android 事件响应的四种实现方式
- struts2中取得web项目的根目录
- wxWidgets——Error: Cannot initialize OLE when using CLR
- android 单元测试
- Swift入门教程10-subscript下标脚本
- Eclipse编辑器基本设置
- 泰戈尔名句
- JavaScript进阶(三) 值传递和引用传递