C++多线程2.beginthread
C++ 多线程2 beginthread 启动线程知识 20131021
Reference: http://blog.csdn.net/laoyang360/article/details/7720656
前言:
之前曾经使用过WINAPI创建线程并且启动的知识,还有线程之间同步的知识,这里讲解一下使用__beginthread的原理和机制。
1._beginthread 简单的介绍
如果我们编写的是C++的程序,不应该使用CreateThread WINAPI接口去创建线程,而是应该使用Visual C++运行库函数_beginthread,退出线程的时候应该使用_endthread。因为_beginthreaex和_endthreadex是CRT的线程函数,所以必须注意编译选项runtimelibrary,使用的是MT或者是MTD(MultiThreaded,debug Multithread);_beginthread函数的参数列表和CreateThread的参数列表完全相同,但是参数名称和类型不是完全的相同。因为Microsoft的C/C++运行库的开的小组认为C/C++运行期函数不应该对Windows数据类型有任何的依赖。
每一个线程都会获得由C/C++运行期库的堆栈分配自己的tiddata内存结构;传递给_beginthreadex的线程函数的地址保存在tiddata内存数据块,传递给该函数的参数也保存在该数据块中;_beginthreadex确实从内部调用CreateThread函数,因为这是创建线程早OS层面上的唯一的方法;当调用CreateThread函数的时候,他会被告知通过调用_threadstartex而不是pfnStartAddr来启动执行新的线程,还有传递给线程函数的从哪回溯是tiddata结构而不是pvParam的地址;如果一切顺利的话,就会像CreateThread那样返回线程句柄,任何操作失败就会返回NULL。
总的来说就是_beginthreadex在内部调用CreateThread函数,在调用之前_beginthreadex做了很多的工作,从而比CreateThread更加安全.
#include <iostream>
#include <string>
#include <process.h>
#include <Windows.h>
using namespace std;
class ThreadX{
private:
int loopStart;
int loopEnd;
int dispFrequency;
public:
string threadName;
ThreadX(int startVal, int endVal, int frequency){
this->loopStart = startVal;
this->loopEnd = endVal;
this->dispFrequency = frequency;
}
static unsigned __stdcall ThreadStaticEntryPoint(void * pThis){
ThreadX* pThX = (ThreadX*) pThis;
pThX->ThreadEntryPoint();
return 1;
}
void ThreadEntryPoint(){
for (int i = loopStart; i <= loopEnd; i++){
cout << threadName << " i = " << i << endl;
Sleep(100);
}
}
};
int main(){
ThreadX * pThX = new ThreadX(0, 10, 2000);
HANDLE hth1 = NULL;
unsigned uiThread1ID;
hth1 =(HANDLE) _beginthreadex(NULL,
0,
ThreadX::ThreadStaticEntryPoint,
pThX,
CREATE_SUSPENDED,
&uiThread1ID);
if (hth1 == NULL){
cout << "failed to create thread 1" << endl;
}
DWORD dwExitCode;
GetExitCodeThread(hth1, &dwExitCode); // shoule be STILL_ACTIVE
cout << "init thread 1 exit code id = " << dwExitCode << endl;
pThX->threadName = "yang1";
ThreadX* pThX2 = new ThreadX(0, 10, 2000);
HANDLE hth2 = NULL;
unsigned uiThread2ID;
hth2 = (HANDLE) _beginthreadex(NULL,
0,
ThreadX::ThreadStaticEntryPoint,
pThX2,
CREATE_SUSPENDED,
&uiThread2ID);
if (hth2 == NULL){
cout << "create thread 2 failed" << endl;
}
GetExitCodeThread(hth2, &dwExitCode);
cout << "init thread 2 exit code id = " << dwExitCode << endl;
pThX2->threadName = "yang2";
ResumeThread(hth1);
ResumeThread(hth2);
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
GetExitCodeThread(hth1, &dwExitCode);
cout << "thread 1 exited with exit code " << dwExitCode << endl;
GetExitCodeThread(hth2, &dwExitCode);
cout << "thread 2 exited with exit code " << dwExitCode << endl;
CloseHandle(hth1);
CloseHandle(hth2);
delete pThX;
delete pThX2;
pThX = NULL;
pThX2 = NULL;
cout << "end program " << endl;
return 0;
}
2.线程临界区
线程之间共享的对象,当修改的时候,只能够一个线程修改,同时不存在其他的线程访问该资源,这就是线程之间的同步问题.在上一篇总结中使用的是CreateMutex函数创建一个HANDLE,这样的话创建一个Mutex,当线程访问资源的时候,使用WaitForSimpleObject(handl, INFINITE);获得该对象的锁,然后再使用完的时候,释放对象锁,ReleaseMutex(handle);
在线程中有一个概念是临界区,在C++中使用这一种实现的,就是用CRITICAL_SECTION 声明一个临界区变量,然后再程序开始的时候,使用InitializeCriticalSelection(CRITICAL_SELECTION*) 初始化临界变量,然后当线程进入临界区的时候,使用EneterCriticalSelection(CRITICAL_SELECTION*);当访问完成的时候使用LeaveCriticalSelection(CRITICAL_SELECTION);
#include <iostream>
#include<Windows.h>
using namespace std;
bool g_bContinue = true;
int g_count1 = 0;
int g_count2 = 0;
DWORD WINAPI ThreadProc(LPVOID lpParam){
for (int i = 0; i < 20; i++)
{
EnterCriticalSection(&g_cs);
g_count1++;
g_count2++;
LeaveCriticalSection(&g_cs);
}
return 0;
}
int main(){
HANDLE g_hThr[2];
InitializeCriticalSection(&g_cs);
g_hThr[0] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
g_hThr[1] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
WaitForSingleObject( g_hThr[0], INFINITE);
WaitForSingleObject( g_hThr[1], INFINITE);
g_bContinue = false;
CloseHandle(g_hThr[0]);
CloseHandle(g_hThr[1]);
DeleteCriticalSection(&g_cs);
Sleep(1000);
cout << "g_count1 = " << g_count1 << "\t g_count2 = " << g_count2 << endl;
}
追梦的飞飞
于广州中山大学 20131022
HomePage: http://yangtengfei.duapp.com
C++多线程2.beginthread的更多相关文章
- Delphi另一个多线程函数:BeginThread用法
Delphi另一个多线程函数:BeginThread━━━━━━━━━━━━━━━━━━━━━━━━━━ Delphi也提供了一个相同功能的类似函数:function BeginThread( ...
- Delphi中线程类TThread实现多线程编程1---构造、析构……
参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...
- [转]C++11 多线程
转载自:http://www.cnblogs.com/zhuyp1015/archive/2012/04/08/2438288.html C++11开始支持多线程编程,之前多线程编程都需要系统的支持, ...
- BCB 多线程的同步与协调
多线程编程是提高系统资源利用率的一种常见方式.它占用的资源更小,启动更快,还可以实现在后台运行一些需时较长的操作.[喝小酒的网摘]http://blog.hehehehehe.cn/a/8498.ht ...
- [转]Delphi多线程编程入门(二)——通过调用API实现多线程
以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread( lpThreadAttributes: Pointer ...
- windows多线程编程(一)(转)
源出处:http://www.cnblogs.com/TenosDoIt/archive/2013/04/15/3022036.html CreateThread:Windows的API函数(SDK函 ...
- delphi 中几种多线程操作方式
在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:http: ...
- C++11 多线程
C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用 ...
- C++11 多线程 教学(2)
C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等, ...
随机推荐
- 『NiFi 学习之路』自定义 —— 组件的自定义及使用
一.概述 许多业务仅仅使用官方提供的组件不能够满足性能上的需求,往往要通过高度可定制的组件来完成特定的业务需求. 而 NiFi 提供了自定义组件的这种方式. 二.自定义 Processor 占坑待续 ...
- 哪个地图API 好用
之前我们能用的地图软件还寥寥无几,而且一个地图包动辄就上百M,还不支持GPS,没有实时路况,没有卫星图,一年也未必更新一次.现如今的地图功能已经极大丰富了,开发者的项目选择性也很大,地图哪个受众比较多 ...
- 带你走进AJAX(1)
ajax是什么? (1)ajax (asynchronouse javascript and xml) 异步的javascript 和xml (2)ajax是一个粘合剂,将javascript.xml ...
- jstl c:choose>、<c:when>和<c:otherwise>标签的简单使用介绍
<c:choose>.<c:when>和<c:otherwise>在一起连用,可以实现Java语言中的if-else语句的功能.例如以下代码根据username请求 ...
- Python中正则模块re.compile、re.match及re.search函数用法
import rehelp(re.compile)'''输出结果为:Help on function compile in module re: compile(pattern, flags=0) C ...
- GIT使用—分支与合并
一.分支名 分支名不能以斜线结尾 分支名不能以减号开头 以斜杠分割的组件不能以点开头(feature/.new) 分支名的任何地方都不能包含连个连续的点 分支名不能包含空格或空白符 分支名不能包含波浪 ...
- 20145310 《Java程序设计》第7周学习总结
20145310 <Java程序设计>第7周学习总结 教材学习内容总结 本周主要进行第十二章和第十三章的学习. Lambda定义:一个不用被绑定到一个标识符上,并且可能被调用的函数. 在只 ...
- 20145312 《Java程序设计》第九周学习总结
20145312 <Java程序设计>第九周学习总结 学习笔记 Chapter 16整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 SUN公司为了简化.统一对数据库的操作, ...
- Win10下配置Java 环境变量
在Win10中配置环境变量的方法跟在Win8和Win7中有些不同,看了看网上好多还是Win7/8里面的配置方法.虽然从原理上基本上没什么问题,但有些细节却会让人很苦恼.特意整理下新的配置方法.我假定你 ...
- java处理json的工具类(list,map和json的之间的转换)
需要下载第三方的jar :net.sf.json import java.io.BufferedReader; import java.io.InputStream; import java.io.I ...