windows多线程基础(5):使用_beginthreadex创建线程(C/C++ Runtime Library考虑)

 标准CRT(C Runtime Library)问世于1970年,没有考虑到将CRT运行于多线程应用程序的问题。
  • 在多线程环境中存在问题的C/C++运行期库变量和函数包括:error, _doserrno, strtok, strerror, asctime, gmtime,malloc等等。这些函数中都存在全局变量或者要访问全局变量(对于malloc来说,进程的堆也算是全全局的了),所以导致多个线程同时访问时,会发生互相影响。这下就会乱套了。
俗话说办法总比问题多,好在知道了问题之后,就会有解法了。
  • 若要使多线程C/C++程序正确运行,必须创建一个数据结构,并将它与使用C/C++运行期库函数的每个线程关联起来。当调用这些库函数时,这些函数必须知道查看属于线程自己的数据块,这样就不会对别的线程产生影响。
那么系统知道在创建新线程时分配该数据块呢?显然不知道。系统管你是用什么语言写的才怪!系统只是帮你把线程创建起来而已,管你用了线程安全还是不安全的函数了没。

既然系统不帮我们干,那么我们就自己干。(是系统不能干么?当然也不是,或许系统是为了让系统内核的接口保持简单而已,不要加那么多的逻辑在里面。在我们的工作当中不是也是么?比如一个特殊的数据格式转换,是在你的模块里做,还是在我的模块里面做,都可以,不过谁做了,谁的逻辑就稍微麻烦些了。)若要创建一个新线程,不要使用操作系统的CreateThread函数,必须调用C/C++运行期库函数_beginthreadex。
unsigned long _beginthreadex(
    void *security,
    unsinged stack_size,
    unsigned (*start_address)(void *),
    void *arglist,
    unsinged initflag,
    unsigned *thrdaddr_
);
  1. _beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的,但是参数名和类型并不完全相同,据说是VC的C/C++运行期库的开发者认为不应该对Windows的数据类型有任何依赖。同样,返回参数为新创建线程的句柄。
  2. 我们知道VC的运行库分为单线程静态链接库、多线程静态链接库、多线程动态链接库(我在VC2013里面草草秒了一眼,貌似没有单线程静态链接库了,但是静态多线程连接库貌似有好几个版本了)。_beginthreadex函数只存在多线程的版本中,在使用多线程编译的时候,VC编译器会加上/MT参数。
  3. VC的运行库提供了源码(位置在Microsoft Visual Studio 12.0\VC\crt\src\threadex.c,我了个去,可以学习一下了同志们),一下是_beginthreadex的源代码:
/*
 * CreateThread 包装
 */
static HANDLE _createThread(
        LPSECURITY_ATTRIBUTES security,
        unsigned stacksize,
        LPVOID ptd,
        unsigned createflag ,
        LPDWORD thrdaddr)
{
    return CreateThread(
                security,
                stacksize,
                _threadstartex,
                ptd,
                createflag ,
                thrdaddr);
}

_CRTIMP uintptr_t __cdecl _beginthreadex (
        void * security,
        unsigned stacksize,
        unsigned ( __stdcall * initialcode ) (void *),
        void * argument,
        unsigned createflag ,
        unsigned * thrdaddr
        )
{
        //这个ptd就是为每个线程分配数据块的指针*/
        _ptiddata ptd;               /* pointer to per-thread data */
        uintptr_t thdl;              /* thread handle */
        unsigned long err = 0L;      /* Return from GetLastError() */
        unsigned dummyid;            /* dummy returned thread ID,线程ID */

               // 检查initialcode非空
        /* validation section */
        _VALIDATE_RETURN( initialcode != NULL , EINVAL , 0);

        /* 申请一个ptd数据结构体,这个数据块对于将要创建线程来说是独有的
         * Allocate and initialize a per-thread data structure for the to-
         * be-created thread.
         */
        if ( (ptd = (_ptiddata)_calloc_crt(1, sizeof
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值