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的更多相关文章

  1. Delphi另一个多线程函数:BeginThread用法

    Delphi另一个多线程函数:BeginThread━━━━━━━━━━━━━━━━━━━━━━━━━━ Delphi也提供了一个相同功能的类似函数:function BeginThread(    ...

  2. Delphi中线程类TThread实现多线程编程1---构造、析构……

    参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...

  3. [转]C++11 多线程

    转载自:http://www.cnblogs.com/zhuyp1015/archive/2012/04/08/2438288.html C++11开始支持多线程编程,之前多线程编程都需要系统的支持, ...

  4. BCB 多线程的同步与协调

    多线程编程是提高系统资源利用率的一种常见方式.它占用的资源更小,启动更快,还可以实现在后台运行一些需时较长的操作.[喝小酒的网摘]http://blog.hehehehehe.cn/a/8498.ht ...

  5. [转]Delphi多线程编程入门(二)——通过调用API实现多线程

    以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread(    lpThreadAttributes: Pointer ...

  6. windows多线程编程(一)(转)

    源出处:http://www.cnblogs.com/TenosDoIt/archive/2013/04/15/3022036.html CreateThread:Windows的API函数(SDK函 ...

  7. delphi 中几种多线程操作方式

    在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:http: ...

  8. C++11 多线程

    C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用 ...

  9. C++11 多线程 教学(2)

      C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等, ...

随机推荐

  1. dev-server.js详解

    转载自:https://www.cnblogs.com/ye-hcj/p/7091706.html dev-server.js详解 require('./check-versions')() var ...

  2. git 常用的撤销操作

    git 开发时的使用流程,从同事那里学习的, 第一步,先建立一个新的分支,可以在GITLAB或通过命令git checkout -b newbranch 或通过IDE插件 第二步,让项目切换到该分支, ...

  3. Hbase环境安装

    说明: (Hbase依赖于HDFS和zookeeper) 参考我的博客: https://www.cnblogs.com/654wangzai321/p/8603498.html https://ww ...

  4. tomcat服务无响应堆栈分析

    tomcat服务突然无响应了,导出内存堆栈和线程堆栈,分析后发现是同步锁使用不合理导致的. [root@prd-dtb-web-01 ~]# [root@prd-dtb-web-01 ~]# jmap ...

  5. Spark高级数据分析· 3推荐引擎

    推荐算法流程 推荐算法 预备 wget http://www.iro.umontreal.ca/~lisa/datasets/profiledata_06-May-2005.tar.gz cd /Us ...

  6. WCF基本知识

    1.开通WCF调试服务: 须在服务端的行为中作如下配置:includeExceptionDetailInFaults="true" 代码如下: <behaviors> ...

  7. Spring事务用法示例与实现原理

    关于Java中的事务,简单来说,就是为了保证数据完整性而存在的一种工具,其主要有四大特性:原子性,一致性,隔离性和持久性.对于Spring事务,其最终还是在数据库层面实现的,而Spring只是以一种比 ...

  8. wix toolset将 cab 打包进msi

    在***wxs中添加配置 <MediaTemplate EmbedCab="yes" /> 下面是一个简单配置:(包含写注册表) <?xml version=&q ...

  9. 20135320赵瀚青LINUX第三章读书笔记

    第三章 进程管理 3.1 进程 进程的定义: 是处于执行期的程序以及它所包含的资源的总称. 线程的定义: 是在进程中活动的对象. 每个线程都拥有一个独立的程序计数器.进程栈和一组进程寄存器. 内核调度 ...

  10. 重新想,重新看——CSS3变形,过渡与动画①

    学习CSS3,觉得最难记忆的部分除了flex特性之外,就要属变形,过渡和动画部分了.作为初学者,总有种犯懒的心理,想着既然IE8浏览器都不完全支持CSS动画属性,还要考虑浏览器兼容问题,那么就不那么着 ...