windows多线程之CreateThread与_beginthreadex区别

2 篇文章 0 订阅

使用多线程非常容易, 以前在linux上学习的时候没有这么详细的区分, 也没有深入的了解多线程, 在linux上只要包含头文件pthread即可, 最近学习windows上才有了很多区分, 例如C++11 新标准的头文件<thread>也是可以创建多线程或者windows.h中的CreateThread_beginthreadex两个都是可以创建多线程的

#include <stdio.h>
#include <windows.h>

/*
	之前一直存在疑惑点, 为什么返回值为void函数就出现不能调用, 说函数类型不匹配, 通过别人的一篇文章才知道原因, 然后查看CreateThread源码发现有这么一个宏定义

typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(
	LPVOID lpThreadParameter
);

定义的函数指针为: 返回值为DWORD 函数参数为void* 名为函数指针PTHREAD_START_ROUTINE的指针
*/
DWORD WINAPI threadFun(LPVOID PM)
{
	printf("%d",GetcurrentThreadId()); 
    return 0;
}


int main()
{
    HANDLE handle = CreateThread(NULL,0,threadFun,NULL,0,NULL);
    WaitForsingleObject(handle,INFINITE);//INFINITE阻塞等待
    CloseHandle(handle);//主进程放弃对线程的控制
    return 0;
}

CreateThread() 是微软在Windows API中提供的线程函数, 该函数会在主函数的进程中创建一个新的线程, 如果创建成果那么函数向线程返回一个句柄, 如果失败则返回NULL, 线程终止运行后, 线程对象仍在系统内中, 必须通过CloseHandle(), 函数来关闭线程对象, 否则会在父进程结束的时候自动销毁;

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES       secAttr,// 描述线程内核对象安全属性的指针,设置为NULL就会使用默认的安全描述符
SIZE_T                      stackSize,//表示线程栈空间大小如果为0那么和创建它的线程相同
LPTHREAD_START_ROUTINE      threadFunc,//线程函数
LPVOID                      param,//线程函数参数列表
DWORD                       flags,//执行状态标志,0表示创建以后可以使用,CREATE_SUSPENDED线程挂起等待, 直到调用ResumeThread()
LPDWORD                     threadID//以长整型返回线程ID号,传入NULL表示不需要返回该线程ID
);

//线程函数的基本形式
DWORD WINAPI Thread1(LPVOID param);

-DWORD是数据类型,WINAPI是函数调用形式,返回32位数据的API函数。 
-需要传递给新线程的任何参数都在CreateThread()的param中指定。线程函数在它的参数中接收这个32位的值。这个参数可以用作任何目的。函数返回它的退出状态。 
- WINAPI是一个宏,所代表的符号是__stdcall。windows API函数采用这种标准调用约定。 
#define WINAPI __stdcall 
stdcall的调用约定意味着: 
1)参数从右向左压入堆栈; 
2)函数自身修改堆栈; 
3) 函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。

CreateThread() 是极其不安全, 容易造成数据的访问出现错误等原因

if(...)
{
    switch(num)
    {
            /*code*/
    }
}

在这个语句的时候如果我们调用多线程就会出现一个问题, 因为没有数据的加锁, 所以如果A线程进入了if语句里面, 与此同时B线程进入, 那么会导致A的线程的num变成了B线程或者相反的情况等

为了解决这个情况,Windows操作系统提供了一种解决方案, 每个线程都有自己独立的内存区域,而这个内存区域由运行库函数_beginthreadex()来负责

在另一篇博文中分析了_beginthreadex的源码和CreateThread的区别, 水平有限只能看懂部分代码, 这里只是对他分析的结果进行自己理解的总结

_beginthreadex()在创建线程时会分配初始化一个_tiddata块, 这个初始化的块就是用来存储线程的独享数据, 新的线程运行的时候首先会将_tiddata与自己关联起来, 把需要保护的数据存入到_tiddata块中, 这样每个线程都只会访问和修改自己的数据而不会篡改其他线程的数据

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值