Python多线程资源竞争 引言 介绍多线程共享全局变量,并研究Python多线程资源竞争导致线程不同步的问题。 利用 线程锁(Lock)机制实现线程同步。 多线程-共享全局变量 运行结果: 列表当做实参传递到线程中 运行结果: 在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全) Python 多线程资源竞争问题 我们就用自定义一个自增线程类继承 类来模拟资源竞争问题。 代码演示 运行结果 运行结果如下: 但你把 设置成 或者更大试下,你会发现多线程自增得不到正确的数,且每次结果都可能不一样。 运行结果如下: 如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确 问题分析 假设当时 ,第一个线程抢到时间片运行,执行完 加法操作,然后刚想执行 赋值操作时被第二个线程抢到线程执行权,且完整执行完 ,由于上个线程还没有完成赋值操作,所以此时 ,然后 切换到第一个线程的上下文环境 进行赋值操作 ,因为第一个线程的加法操作已经完成只要继续进行赋值就行,但此时 已经被第二个线程赋值变成了 ,所以再让 已经让 重复赋值了,因此数据结果会不正确。 为什么 比较小的数的时候,很难出现数据结果不正确呢,可能 对这些小数据计算很快,一下子就完成简单的 操作。而到了几百万、千万,抢到的时间片可能不够用,无法一次完成全部操作,且非原子性操作,可进行线程的上下文切换。 原子操作()是不需要 ,这是多线程编程的老生常谈了。所谓 *原子操作*是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 (切换到另一个线程的上下文) 是非原子性操作,要先进行 加法操作,然后进行 赋值操作。 线程同步 同步的概念 同步就是协同步调,按预定的先后次序进行运行。如: 你说完,我再说。 ”同”字从字面上容易理解为一起动作 其实不是,”同”字应是指协同、协助、互相配合。 如进程、线程同步,可理解为进程或 线程 A 和 B 一块配合,A 执行到一定程度时要依靠 B 的某个结果,于是停下来,示意 B 运行,B 执行,再将结果给 A,A 再继续操作。 线程锁机制 互斥锁 当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。 互斥锁为资源引入一个状态:锁定 / 非锁定 某个线程要更改共享数据时,先将其锁定,此时资源的状态为 锁定,其他线程不能更改;直到该线程释放资源,将资源的状态变成 非锁定,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的准确性。 对于上文提出的那个计算错误的问题,可以通过线程同步来进行解决 思路,如下:系统调用 t1,然后到 g_num 的值为0,此时上一把锁,即不允许其他线程操作 g_numt1 对 g_num 的值进行+1t1 解锁,此时 g_num 的值为1,其他的线程就可以使用 g_num了,而且是 g_num 的值不是 0 而是 1同理其他线程在对 g_num 进行修改时,都要先上锁,处理完后再解锁,在上锁的整个过程中不允许其他线程访问,就保证了数据的准确性 模块中定义了 类,可以方便的处理锁定: 运行结果如下: 可以看到最后的结果,加入互斥锁后,其结果与预期相符。 注意:如果这个锁之前是没有上锁的,那么 不会堵塞如果在调用 对这个锁上锁之前 它已经被 其他线程上了锁,那么此时 会堵塞,直到这个锁被解锁为止 死锁 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 尽管死锁很少发生,但一旦发生就会造成应用的停止响应。下面看一个死锁的例子 运行结果: 此时已经进入到了死锁状态,可以使用 退出 避免死锁程序设计时要尽量避免死锁(银行家算法)添加超时时间等 银行家算法 背景知识 一个银行家如何将一定数目的资金安全地借给若干个客户,使这些客户既能借到钱完成要干的事,同时银行家又能收回全部资金而不至于破产,这就是银行家问题。这个问题同操作系统中资源分配问题十分相似:银行家就像一个操作系统,客户就像运行的进程,银行家的资金就是系统的资源。 问题的描述 一个银行家拥有一定数量的资金,有若干个客户要贷款。每个客户须在一开始就声明他所需贷款的总额。若该客户贷款总额不超过银行家的资金总数,银行家可以接收客户的要求。客户贷款是以每次一个资金单位(如1万RMB等)的方式进行的,客户在借满所需的全部单位款额之前可能会等待,但银行家须保证这种等待是有限的,可完成的。 例如:有三个客户C1,C2,C3,向银行家借款,该银行家的资金总额为10个资金单位,其中C1客户要借9各资金单位,C2客户要借3个资金单位,C3客户要借8个资金单位,总计20个资金单位。某一时刻的状态如图所示。
对于 a图 的状态,按照 安全序列 的要求,我们选的第一个客户应满足该客户所需的贷款小于等于银行家当前所剩余的钱款,可以看出只有 C2客户 能被满足:C2客户需1个资金单位,小银行家手中的 2 个资金单位,于是银行家把 1 个资金单位借给 C2客户,使之完成工作并归还所借的 3 个资金单位的钱,进入 b图。同理,银行家把4个资金单位借给 C3客户,使其完成工作,在 c图 中,只剩一个 客户C1,它需 7 个资金单位,这时银行家有 8 个资金单位,所以C1也能顺利借到钱并完成工作。最后(见图d)银行家收回全部 10个资金单位,保证不赔本。那么客户序列 就是个安全序列,按照这个序列贷款,银行家才是安全的。否则的话,若在图b状态时,银行家把手中的4个资金单位借给了 ,则出现不安全状态:这时 均不能完成工作,而银行家手中又没有钱了,系统陷入僵持局面,银行家也不能收回投资。 综上所述,银行家算法是从当前状态出发,逐个按安全序列检查各客户谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户,……。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。 新建文件夹X 大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/70942.html