windows下的多线程编程

多线程
多线程是指在一个进程中,开启多个线程,这些线程根据一定的规则(或者无规则)进行抢夺cpu时间来进行,营造出一种并发处理的感觉,提高处理速度,同时也提高用户的体验,在cpu多核情况下,更能提高处理效率
多线程处理需要注意的地方
1.对于处理同样工作的线程,需要处理好线程之间的逻辑。如生产者与消费者的问题中,消费者使用多线程提高消费速度,那么如何避免线程消费同样的消费品是需要考虑的。
2.对于处理不同工作的线程,需要考虑的是线程之间的联系问题,同样生产者与消费者的问题,生产者与消费者各用一个线程,那么必须要起码有一各生产者已经生产完,才能进行消费,如果消费完了,生产者还没生产下一件,需要挂起当前进程。
3.公共资源的问题,对于多线程,最麻烦也是最重要的就是考虑线程之间涉及的公共资源,此时需要进行加锁,设置临界区进行处理。具体问题需要进行具体分析:如公共资源,如果已经写完,只剩下读取操作,则不用加锁;又如对于vector<vector<string>> a,每个线程对且仅对一个不同的元素进行操作,则也不用进行加锁,但如果处理元素有交叉,则要加锁,或者进入临界区处理。
4.线程的数量问题,对于多线程的程序而言,并不是线程越多效率越高,线程的创建以及销毁也是需要时间,此外对于需要多个短时间运行线程,可以考虑使用线程池来进行操作,避免过于频繁地创建线程。
windows多线程:
windows提供创建线程的函数:
//不推荐使用
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,//安全设置,一般设为NULL
SIZE_T dwStackSize,// 初始栈大小(私有),设为0与主线程一致
LPTHREAD_START_ROUTINE lpStartAddress,//线程函数
LPVOID lpParameter, //线程传入参数 ,类型是void型指针
DWORD dwCreationFlags, //启动选项,0代表立即执行
LPDWORD lpThreadId // 线程ID,默认为NULL,线程的ID是唯一的
)
//推荐使用_beginThreadex()原因请看:

http://blog.csdn.net/morewindows/article/details/7421759

include<process.h>
_beginThreadex(
void*security,//安全设置,一般设为NULL
unsigned stack_size,// 初始栈大小(私有),设为0与主线程一致
unsigned ( __stdcall *start_address )( void * ),//线程函数,即函数名称
void *arglist,   //线程传入参数 ,类型是void型指针
unsigned initflag,//启动选项,0代表立即执行
unsigned *thrdaddr// 线程ID,默认为NULL,线程的ID是唯一的
)

线程函数原型(多个线程可以共用一个线程函数):

void NTAPI FUN(
PTP_CALLBACK_INSTANCE Instance, // 回调函数的终止操作
PVOID Context //void*类型参数,可在函数内进行强制类型转换
)
***windows默认线程池**:

此外,windows还允许我们使用默认的线程池以及对默认线程池的环境进行设置(默认线程池中线程数量最多500,最小为1,这里只谈论默认线程池的调用方式)
让线程池执行一个请求:

BOOL TrySubmitThreadpoolCallback(
PTP_SIMPLE_CALLBACK pfnCallback, //线程函数
PVOID pvContext,//void*类型参数
PTP_CALLBACK_ENVIRON pcbe//线程池环境设置类型参数
)

但是,对于线程数量过多时,windows不建议我们使用上面的“一步式”申请线程的函数,因为此时有可能调用失败。windows建议我们先创建工作项,再提交工作项的方法来进行。
创建工作项:

PTP_WORK CreateThreadpoolWork(
PTP_SIMPLE_CALLBACK pfnCallback, //线程函数
PVOID pvContext,//void*类型参数
PTP_CALLBACK_ENVIRON pcbe//线程池环境设置类型参数
)

提交工作项
VOID SubmitThreadpoolWork(PTP_WORK);
对于提交上去的工作项,windows提供一个函数允许我们进行取消,或者等待其处理完成(相当于阻塞)
若工作项没提交,则立刻返回不执行操作;若参数为TRUE,函数会尝试取消工作项,但正在处理则等待完成后返回;若参数为FALSE,则会将调用此函数的线程挂起,直至工作项已处理完且对应线程也被收回并准备处理下一个工作项。

VOID WaitForThreadpoolWorkCallback(
PTP_WORK pWork,
BOOL bCancelPendingCallback
)

一般而言,对于要使用线程池,推荐使用boost 的thread库,里面已经封装好的,比windows默认的线程池好用很多。
多线程相关处理
临界区:访问临界资源的代码段称为临界区。临界区只允许一个线程(进程)进入,若已有线程在处理,其余线程必须等待。

CRITICAL_SECTION g_cs;//临界区变量的定义
InitializeCriticalSection(&g_cs);//初始化
EnterCriticalSection(&g_cs)//进入临界区
...//相关代码
LeaveCriticalSection(&g_cs)//离开临界区

原子操作:原子操作是指不会被线程调度机制打断的操作。以i++为例,i++在实际中会先进行读取变量,移到寄存器,寄存器加1,再返回设置,此时有可能会被其余线程打断,若i为公共资源,会产生难以想像的后果。
windows为我们提供了几个原子操作的函数:

LONG InterlockedDecrement(&LONG);//减1
LONG InterlockedIncrement(&LONG);//增1
//还有一些其他函数大家有兴趣可以搜搜。
//注意一般使用这种原子操作,最好使用返回值进行判断条件,可以避免多线程产生的问题

其他互斥锁,自旋锁,信号量这些博主暂时没具体使用过,有空再补~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值