关于线程的基本概念,博友可参考我的c#Thread文章.本文所讨论的是在c++下使用线程.
本文只是线程的一个浓缩版,目的是可以让大家能快速的熟悉在c++是使用线程,希望大家踊跃拍砖.
用API函数CreateThread可创建线程.该函数原型为
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORN dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
)
该函数参数较多,不过不用急,我们一步一步来分析参数.
1:lpThreadAttributes 这个参数是指向SECURITY_ATTRIBUTES结构的指针.SECURITY_ATTRIBUTES结构主要主用是设置线程安全性的,我们在用
CreateThread创建线程的时候可用NULL给它赋值(让创建的线程使用默认的安全性).
2:dwStackSize 这个参数的主要是设置创建的线程栈的大小.这里出现了一个技术词(栈).
栈是数据在内存中的一个位置。
提到栈我们就顺便提下数据在内存中的存放形式。
一般有如下形式
栈:由编译器自动分配并且释放
堆:一般由程序员手动释放.
寄存器:一般存放全局变量和静态变量等
对于int a这样的声明,自动自动为a在栈中开辟空间,而 person *p=new person这样的声明来说
变量p就是存放在堆中,并且需要手动释放入delete p;在c#或java这样的语言来说回收由系统自动回收.
一般我们不需要手动释放.
在这里dwStackSize意义是设置线程dwStackSize的大小.如果这里设为0就默认使用和条用线程的函数一样大。
3:lpStartAddress 指向LPTHREAD_START_ROUTINE类型的函数指针.是线程的起始地址
4:pParameter 命令行参数 可为空
5:dwCreationFlags 创建线程的附加标记.它可以是两个值中的一个可以是CREATE_SUSPENDED或者0,如果是CREATE_SUSPENDED,线程创建后处理
暂停状态,为0则理解执行
6:lpThreadId 这个参数是一个返回值,用来接收线程ID。。
我们大致对CreateThread函数有所了解后,下面我们用一个简单的程序来说明下怎么使用线程
我们用VC6创建一个空的控制台程序
#include <windows.h>
#include <iostream.h>
//
首先声明下线程函数地址
DWORD WINAPI FunOne(
LPVOID lpParameter
);
void main()
{
HANDLE hThread1;
hThread1=CreateThread(NULL,
0,FunOne,NULL,
0,NULL);
CloseHandle(hThread1);
//
关闭打开的线程句柄
/*
Sleep(1);
这里如果不添加Sleep函数就会看见输出Response FunOne
至于为什么请大家思考思考
*/
cout<<
"
Response main
"<<endl;
}
DWORD WINAPI FunOne(
LPVOID lpParameter
)
{
cout<<
"
Response FunOne
"<<endl;
return
0;
};
线程同步
关于同步的概念在此我们也不讲解呢,由不太明白的博客可参考我的c#系列文章。在这里我将定义一个全局变量,用两个创建的线程来同事访
问该变量.
这里我们用到一个互斥对象mutex.
我们可以用CreateMutex函数来创建互斥对象.互斥对象包含一个线程ID和一个计数器.ID标识当前线程的ID,计算器标明该线程使用互斥对象
的次数.
CreateMutex的函数原型入下
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwer,
LPCTSTR lpName
)
1:lpMutexAttributes 安全性 和CreateThread第一个参数相同
2:bInitialOwer BOOL类型 为true的话则创建者线程拥有使用互斥对象的拥有权,为false则不活的创建对象的所有权
3:lpName 互斥对象的名称
ReleaseMutex 释放互斥对象的拥有权.和WaitForSingleObject函数成对使WaitForSingleObject函数的功能是请求互斥对象的拥有权..
下面是Demo
#include <windows.h>
#include <iostream.h>
//
首先声明下线程函数地址
DWORD WINAPI FunOne(
LPVOID lpParameter
);
DWORD WINAPI FunTwo(
LPVOID lpParameter
);
int TxtNum=
100;
HANDLE hMutex;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,
0,FunOne,NULL,
0,NULL);
hThread2=CreateThread(NULL,
0,FunTwo,NULL,
0,NULL);
CloseHandle(hThread1);
//
关闭打开的线程句柄
CloseHandle(hThread2);
hMutex=CreateMutex(NULL,FALSE,NULL);
Sleep(
5000);
}
DWORD WINAPI FunOne(
LPVOID lpParameter
)
{
for(
int i=
1;i<
100;i++)
{
//
INFINITE参数表示WaitForSingObject用该等待直到获得所有权
WaitForSingleObject(hMutex,INFINITE);
if(TxtNum>
0)
{
cout<<
"
妈妈正在做第
"<<TxtNum--<<
"
道菜
"<<endl;
}
ReleaseMutex(hMutex);
}
return
0;
}
DWORD WINAPI FunTwo(
LPVOID lpParameter
)
{
for(
int i=
1;i<
100;i++)
{
//
INFINITE参数表示WaitForSingObject用该等待直到获得所有权
WaitForSingleObject(hMutex,INFINITE);
if(TxtNum>
0)
{
cout<<
"
妈妈正在做第
"<<TxtNum--<<
"
道菜
"<<endl;
}
ReleaseMutex(hMutex);
}
return
0;
}
本片文章篇幅不长,欢迎交流