使用锁代码操作不当就会产生死锁的情况 。
什么是死锁
死锁:当线程A持有独占锁a , 并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试获取独占锁a的情况下,就会发生AB两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁 。即死锁是指多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程都将无法向前推进 。
所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源 。
死锁代码
python线程间通信
如果各个线程之间各干各的,确实不需要通信 , 这样的代码也十分的简单 。但这一般是不可能的,至少线程要和主线程进行通信,不然计算结果等内容无法取回 。而实际情况中要复杂的多,多个线程间需要交换数据 , 才能得到正确的执行结果 。
python中Queue是消息队列,提供线程间通信机制,python3中重名为为queue,queue模块块下提供了几个阻塞队列,这些队列主要用于实现线程通信 。
在 queue 模块下主要提供了三个类,分别代表三种队列,它们的主要区别就在于进队列、出队列的不同 。
简单代码演示
此时代码会阻塞 , 因为queue中内容已满,此时可以在第四个queue.put('苹果')后面添加timeout , 则成为 queue.put('苹果',timeout=1)如果等待1秒钟仍然是满的就会抛出异常,可以捕获异常 。
同理如果队列是空的 , 无法获取到内容默认也会阻塞,如果不阻塞可以使用queue.get_nowait() 。
在掌握了 Queue 阻塞队列的特性之后,在下面程序中就可以利用 Queue 来实现线程通信了 。
下面演示一个生产者和一个消费者,当然都可以多个
使用queue模块,可在线程间进行通信 , 并保证了线程安全 。
协程
协程,又称微线程,纤程 。英文名Coroutine 。
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源) 。为啥说它是一个执行单元,因为它自带CPU上下文 。这样只要在合适的时机,我们可以把一个协程 切换到另一个协程 。只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的 。
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的 , 并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定 。
在实现多任务时,线程切换从系统层面远不止保存和恢复 CPU上下文这么简单 。操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作 。所以线程的切换非常耗性能 。但是协程的切换只是单纯的操作CPU的上下文 , 所以一秒钟切换个上百万次系统都抗的住 。
greenlet与gevent
为了更好使用协程来完成多任务,除了使用原生的yield完成模拟协程的工作,其实python还有的greenlet模块和gevent模块,使实现协程变的更加简单高效 。
greenlet虽说实现了协程,但需要我们手工切换,太麻烦了,gevent是比greenlet更强大的并且能够自动切换任务的模块 。
其原理是当一个greenlet遇到IO(指的是input output 输入输出 , 比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行 。
模拟耗时操作:
如果有耗时操作也可以换成,gevent中自己实现的模块,这时候就需要打补丁了 。
推荐阅读
- 手柄赛车游戏,手柄赛车游戏叫什么
- 1155什么cpu好,1155cpu推荐
- 微网站的制作,微网站制作开发
- php增加某一列数据 php添加
- 怎么进入redis界面,如何进入redis数据库
- php数据库行锁,php数据库设计
- vb.net数据库编程 vb数据库开发实例视频教程
- jqueryflot柱状图,html柱状图插件
- 家庭如何融入互联网营销,家庭如何融入互联网营销工作