线程(vc)

       我主要是做VC下的c++工作,因此对VC比较熟悉的人会对本篇文章有更多的共同的感触吧。

        我刚毕业的时候,非常害怕,害怕一个鼠标点击函数执行半截被中断或者里面的代码中的变量被其他莫名奇妙的东西给篡改。实际上mfc会话框程序,只有一个主线程,可以不用考虑这些事情的,有些杞人忧天。

       这篇文章是09年写的,后来多年后的认识也加了进去。比如SOCKET消息和OnTimer处理的认识,我不知道到底这些消息的处理是不是mfc在后面起了一个单独的线程来激发,要是如此OnTimer里面的函数处理就要小心要加互斥了,后来在苏哥的指点下,进行验证。在OnTimer函数中加Sleep(60*1000);如果界面假死没有反应说明OnTimer是在主线程中被调用的。同理OnReceive也可验证。当然你调用recv,基本上是启动接收线程了,别论。

        简明扼要的说就是只要你不在mfc中启动新线程,你就不需要担心,一段代码执行半截被挂起的情况,也就不用考虑互斥临界区的问题了。但是往往我们需要加入线程,为了处理事务,不让界面卡顿或者为了更快的处理事务,比如迅雷下载,就起了很多个下载线程。

       为什么我们要启动线程?启动多个线程后,就代表着一段代码,就可能被多个线程访问,造成此代码中的变量不可控(成员变量不可控,局部变量,因为每次函数执行都有局部变量环境的保存,因此局部变量不用考虑),这种并发该如何在程序中解决。

     1 为什么我们要启动线程,刚把原因做了简单的介绍。最主要的原因我们知道CPU的速度非常快,电脑的上的其他操作比较慢,比如硬盘上文件的读取就比较慢,我们为了充分利用CPU,才启动多个线程为我们的应用服务。举个例子,比如你正在从电脑上往U盘上拷贝电影,你想想往U盘写的过程,cpu执行指令写,然后磁盘操作,磁盘写的时候,CPU还有90%的空闲;这个时候你可以利用CPU空闲的时间,从内存中已经加载的电影内容,进行预览。拷文件和预览观看电影同时进行。再举个例子,我看能不能进一步把你说迷糊了。就是搬运工往传送带上放东西,那传送带就是CPU,能力强,多个搬运工来往往传送带上放东西,传送带都能处理的过来;可以理解搬运工就是多个子线程。哎,算了不举例子了,我自己都迷糊了。

     2 为什么要考虑并发问题。因为虽然从宏观上讲充分利用cpu资源,可以并发任务,但是CPU执行指令是一条一条执行的。当启动多个线程时,就会发生指令中断,指令中断造成的结果,就是一个线程的执行被挂起;执行另外的线程,另外的线程就可能访问前者访问的东西,造成脏数据。

     3 下面我们还是讲怎么解决并发的问题了,因为涉及到一段代码会被多个线程同时访问,我们就需要在这段代码上下加上临界区,进的时候加锁,出的时候解锁。进的时候先判断锁时候在解着,是才能执行下一句代码,这样保证这段代码数据是单步执行,不会出问题的。当然没必要在整段代码加,可以在访问成员变量,或者全局变量时加上。项目上一般多数都有个内存管理链表,来管理互斥数据,在链表上的添加、取数据时加上互斥。比如在线看视频,简单的是接收网络数据一个线程,对数据进行解码一个线程,这样两个线程同时工作,观看更流程;如果你把视频解码也放在一个线程里面,你想想,一个视频解码耗费时间多,等解码完了才能去接收下一步的数据,你想想在解码的时候,接收工作本可以充分空闲CPU的,时间被白白浪费了。当然了接收起更多的线程,更好,你就不用等了好一会,才能看到那鸡动的视频了。

     希望你能够平心的无聊的看到这里,下面我画个简单的图,实际上mfc的recv去取数据的时候,可能数据已经被网卡放在SOCKET系统接收缓存中了吧。


我也不知道理解对不对,反正我是想说明白,哎。

 下面是本人对线程利用的一些总结。你看到这里,说明你已经只要两年的c++经验了。

1 慎用线程,尽量不要用,若用,程序的整个逻辑会一塌糊涂,你补救都补救不过来。

2 如果整个程序的某一块要提高效率,与其他模块牵扯不多,最好了,就把线程封装到这个模块中。

3 假若这个模块是核心,又确实要用到线程,你就需要把所有相关的业务统一管理,以消息的形式发送这个线程的消息队列里,统一管理,逐条消息进行处理,就不会有同时访问造成的数据Delete错误了。

拿我2010年做的一个项目吧来说,我们当时做呼叫中心的二次开发。板卡的开发比较简单,厂商用的是OnTimer遍历机制,大家知道OnTimer是在主进程的主线程中执行的,因此不会有异步的问题。但是一体机就麻烦了,用的是回调,经过验证回调实在厂商的底层的一个线程中执行,悲剧了,回调所激发的底层设备消息,然后上层业务的作息的呼叫事件等,是在主线程中直接调用底层的函数,两个线程同时可能调用一个函数了或者对象,当时我们也想到了消息队列,就是刚的思想统一管理设备消息。但是两个问题,造成软件还是不稳定,第一个就是当时用的是mfc的postMessage,postMessage是基于窗体的,因此当界面有卡顿的时候就会有消息丢失现象。第二个问题就是当时统一所有消息不彻底,有的函数执行并没有统一到那个主线程里(这里的主线程,是我们主要用来处理业务的线程,并非mfc的主进程的主线程),应该叫做业务主线程。思路上应该是底层的设备消息(底层线程激发),上层作息操作消息(主进程里的主线程激发)都要统一发送给主业务线程,由主业务线程统一管理,循环依次取消息进行处理。

当然了,网上有很多别人封装好的消息管理链表,线程对象等,你都可以拿过来用。

当然具体的业务具体的对待,是个艰巨的活,希望我们能够有收获,理顺我们的代码,删除多余代码,多测试,以备后面可以重复利用。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值