精易论坛

标题: 分享我对多线程的理解 [打印本页]

作者: 年少无知丿    时间: 2015-11-13 16:07
标题: 分享我对多线程的理解
最近在写多线程方面的程序,途中经历苦不堪言....也不多说什么,写下我对多线程的理解吧,可能有很多理解的地方不对,如果有什么好的理解,希望告诉我。
一、进程与线程的关系:
    看了一些这方面的书,里面写的很详细,但是很难理解,我总结了下
    ①进程就是一个执行了的程序。
    ②进程包含线程。
二、线程与线程句柄:
    ①线程句柄可以对线程进行挂起、恢复、结束等操作。
    ②线程句柄是线程创建时会返回的一个整数型数据。
三、线程的操作:
    ①挂起:简单点说就是把暂停线程,先不让它执行;专业的说CPU不给线程分配CPU资源,但是线程还是占有内存资源,也就是说线程被挂起但还是存在。
    ②恢复:简单理解就是继续线程这是相对挂起的线程来说的,挂起后你还希望线程之后运行,再把它恢复,这时CPU就会给它分配CPU资源。
    ③结束:这个就像关闭程序似得,系统把线程给关闭了;专业的说,CPU不再给线程分配CPU资源,而且内存资源也被销毁了。

四、多线程的注意事项
    ① 多线程是不是越多越快,这需要看运行程序的计算机性能,性能高的人自然是越多越快,但是性能差的计算机,使用大量线程,就会导致CPU高峰,从而造成线程堵塞,如此而来运行速度更慢了,所以什么性能的计算机需要与线程数配对。
    ②
线程的执行顺序不一定是按照创建时的顺序执行的,因为CPU处理线程是不确定的顺序。
    ③
如果线程需要对窗口组件操作,那么尽量使用许可区(许可区后面我会详细的介绍的,因为这个东西很重要)如果不使用的话,可能会引起程序错误等情况,而这个错误是随机的。(目前为止我只知道用许可区会降低出错概率,但没找到直接又安全的调用窗口组件的方法,有大神了解的话,麻烦告诉一下,谢谢)
    ④读写共享资源时最好使用许可区,此点与三-③一样,如果能清晰明了的判断不使用许可区也没问题的话,可以选择不使用。
五、许可区 (临界区)
    ①什么是许可区,简单的理解,就是一段代码,该代码需要被多个线程调用,但同时仅能让一个线程调用。
    ②根据五-①的要求,如果多个线程同时需要进入许可区访问该代码,一次只能允许一个线程进入访问,其他线程将会被挂起,等待进入的线程访问完毕退出许可区再进入。所以,如果整个线程都在许可区里,那么看似是多线程实际上是单线程在执行。
    ③根据五-②的要求,多线程
需要避免经常出现进入需等待的许可区,因此许可区的代码需要有执行速度快的特点,也就是执行该代码耗时小,这样就会避免线程被挂起等待现象
    ④第四项经常说道访问共享资源时尽量使用许可区,因为如果多个线程同时在访问全局变量A时,会出现计算错误,比如所有线程都要操作A=A+1,局部变量B=A-1
,就会出现线程C已经执行完A=A+1了但还没执行B=A-1时线程D就在执行A=A+1了,这样就出现了计算错误。此时需要用的许可证在访问变量A之前进入许可区,访问完毕再退出许可区。代码就可以写成这样:进入许可证(许可证),A=A+1,B=A-1,退出许可证(许可证)。这样线程C进入许可证后,之后的线程将会自动挂起,等待线程C退出许可证后,之后的线程就自动恢复并进入许可证。
    ⑤这里我说一个坑,估计大家都会犯这个错误,我也在这个误区里蹲了不少时间。在访问共享资源,进入许可区时,要使用同一个许可区,如果多个线程使用各自的许可区进入,那么这就没有意义了。因为一个许可区只能让一个线程进入,多个许可区不就多个线程都能进入了吗,那此时许可区就无意义了。
    ⑥许可区的唯一缺点:就是不知道我是否真正进入该许可区
以上就是我对多线程的理解



接下来再讲讲多线程程序调试时没有问题,但是编译出来后就会出现程序崩溃的原因。
一般出现这种情况多在生成了程序后,调试时候数据不太多一般察觉不到。其原因是多线程对于双核CPU亲和性上的问题
解决方案很简单
.版本 2
.DLL命令 SetProcessAffinityMask, 整数型, , , 公开, 设置CPU亲和性 进程句柄 返回CPU号

    .参数 hProcess, 整数型
    .参数 hProcess, 整数型

.DLL命令 SetThreadAffinityMask, 整数型, , , 公开, 设置CPU亲和性 线程句柄
    .参数 hProcess, 整数型
    .参数 Mask, 整数型

.DLL命令 GetCurrentProcess, 整数型, , , 公开, 获取当前进程的一个伪句柄 一般是-1

      
.DLL命令 GetCurrentThread, 整数型, , , 公开, 获取当前线程的一个伪句柄 一般是-2

导入好这些dll后
在程序运行前加入该代码
SetProcessAffinityMask (-1, 1)就OK了


作者: 断水流师兄    时间: 2016-3-22 23:08
学习下理论。。
作者: 戏雨流年    时间: 2016-3-25 17:41
讲的挺好的  很容易理解
作者: 易语言12345    时间: 2016-3-26 10:34
很不错!!
作者: 知男而推    时间: 2016-3-26 14:07
可以可以
作者: Able软件    时间: 2016-3-26 14:32
SetProcessAffinityMask (-1, 1)算是明白这句代码的意思了
作者: 小小C    时间: 2016-3-26 21:38
佩服楼主,看这么一大堆的理论...
作者: 悟空科技    时间: 2016-3-27 21:19
设置cpu亲和性后就变单核运行了
作者: a86947820    时间: 2016-3-29 16:06
感谢分享,很给力!~
作者: lrh3344521    时间: 2016-4-2 18:26
MARK....................
作者: 正鑫软件开发    时间: 2016-4-3 10:56
总结的很不错
我一般不用许可证   弄一个全局变量  控制线程进入
作者: 年少无知丿    时间: 2016-4-3 23:28
孤灯独饮 发表于 2016-4-3 10:56
总结的很不错
我一般不用许可证   弄一个全局变量  控制线程进入

这样还是会有锁死的问题
作者: q317824100    时间: 2016-4-8 20:52
讲解到位,支出楼主
作者: 晴雯晴雯    时间: 2016-4-10 12:14
感谢分享,很给力!~
作者: 81664702    时间: 2016-4-25 12:52
学习下理论。。
作者: LzothTeam    时间: 2016-5-15 11:36
  理论知识我得补补了,一大堆名词我都听不懂
作者: q7867401    时间: 2016-7-9 18:38
又让我认识了一些东西 我还没有接触到这里来  先行学习了 楼主非常给力
作者: dhr008    时间: 2016-7-18 00:45
此处应该有掌声 浅显易懂 收藏学习了

作者: 已注销234264    时间: 2016-7-19 09:25
提示: 作者被禁止或删除 内容自动屏蔽
作者: 难解    时间: 2016-7-20 10:28
中国熊 发表于 2016-3-27 21:19
设置cpu亲和性后就变单核运行了

为何,求教。。。qq1141067426
作者: jokerhuman    时间: 2016-7-30 15:15
理论知识往往使我们缺乏的
作者: jinguer    时间: 2016-8-6 04:37
学习了,不错
作者: 风过长街    时间: 2016-8-26 20:11
最近也准备学多线程,这个很详细,学习下
作者: ysbdsn    时间: 2016-9-2 09:54
留个记号,很好
作者: 8884274    时间: 2016-9-3 00:45
大神写个例子出来吧

作者: 已注销370852    时间: 2016-9-3 20:28
提示: 作者被禁止或删除 内容自动屏蔽
作者: ysbdsn    时间: 2016-9-6 14:07
讲的挺好的  很容易理解
作者: w8659000    时间: 2016-9-12 17:36
二、线程与线程句柄:
    ①线程句柄可以对线程进行挂起、恢复、结束等操作。
    ②线程句柄是线程创建时会返回的一个整数型数据。
作者: ysbdsn    时间: 2016-9-14 14:03
留个记号,讲得好
作者: 374237370    时间: 2016-9-19 12:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: 泪无言    时间: 2016-9-19 22:38
谢谢,谢谢
作者: woool    时间: 2016-9-27 00:03

作者: liuliuliuzb    时间: 2016-9-28 13:27
BUcuo 很好的
作者: 简单啲    时间: 2016-10-4 00:04
谢谢大神分享,
作者: 草?泥?马    时间: 2016-10-8 11:47
        感谢分享,很给力!~
作者: 笑拥孤独    时间: 2016-10-8 17:14
感谢楼主分享 - 纯手打
作者: astom    时间: 2016-10-19 02:56
感谢楼主分享很给力
作者: SeeYouAgain    时间: 2016-10-19 16:31
看不懂但是我只是支持楼主
作者: LR柒月    时间: 2016-10-19 16:35
谢谢分享,很有用。
作者: Hookstar    时间: 2016-10-22 02:20
学习了,讲解的透彻,易懂
作者: 昨天的你    时间: 2016-10-22 14:02
半懂不懂
作者: 99270603    时间: 2016-10-29 12:23
游戏多开,用线程刷新辅Zhu界面上的信息会导致辅Zhu崩溃么?
作者: 午夜猩红点缀丶    时间: 2016-10-29 13:59
- - 支持一下  
作者: 四角裤    时间: 2016-11-2 01:18
学习了。。。
作者: 爱被爱时    时间: 2016-12-15 04:51
新手上路,很受益
作者: 咱得有自己独特    时间: 2017-1-12 17:40
将的很好,我想知道com到底该用在哪里,线程里面调用子程序的话还需要在子程序里面使用许可证吗,直接在子程序里面创建许可证进入退出完了直接删除这样可以吗 3个问题谁能回答一下谢谢
作者: khfhk888    时间: 2017-2-2 16:59
学到东西了!
作者: QQ736592720    时间: 2017-6-9 22:41
感谢您的支持,精易有你更精彩!感谢您的支持,精易有你更精彩!
作者: 镇魂    时间: 2021-1-28 19:20
总结的不错!!
作者: 79515150    时间: 2021-11-1 11:28
很好,谢谢
作者: 气质征服一切    时间: 2022-3-13 10:53
这里并不能用CPU高峰来理解,专业名词叫做线程切换,当你的cpu只有1线程的时候,他的多线程运行步骤是,第一个线程运行10毫秒,然后暂停并且保存,然后切换下一个线程,然后在暂停保存在切换,来来回回的,这就是CPU 1线程的多线程运行方式,这也是为什么cpu差一点的线程多了反而速度越慢的原因,因为cpu会来回的切换线程,然后在读取数据在执行,线程越多,切换次数就越多,所以导致多开线程,会很慢的关键点,另外如果仅仅只是记录数量完全可以使用原子,并且SetProcessAffinityMask 这个api设置cpu亲和度的意思是,设置线程在指定的cpu运行,由于指定了cpu所以内存方面问题可以大大降低风险,但是有个缺点是速度变慢了    (备注以上说的多线程运行步骤指的是单核cpu的运行步骤,主要是为了科普cpu单核运行多线程的原理)  另外并不是所有的多线程都适合SetProcessAffinityMask,如果并发特别高,然后又设置了SetProcessAffinityMask,很有可能会出现崩溃(本人亲测)
作者: 脚本爱好者    时间: 2023-3-14 21:25
讲的挺好的  很容易理解
作者: aa6536    时间: 2023-11-21 23:02
讲的挺好的  很容易理解




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4