一:死锁
在死锁之前需要先了解的概念是“可抢占资源”与“不可抢占资源”【此处的资源可以是硬件设备也可以是一组信息】,因为死锁是与不可抢占资源有关的。
可抢占资源:可以从拥有他的进程中抢占而不会发生副作用。e.g:存储器就是一类可抢占资源(假设有A, B两个进程都想用打印机对256MB的用户内存进行打印,若A已经获得打印机并且开始打印,但是在没有打印完成其时间片就用完并被换出了,此时B进程开始运行“抢占了”内存并开始请求打印机,但是A进程还拥有打印机所以B进程没有抢占打印机成功,此时由于双方都缺少一个对方拥有的资源,双方都不能执行,有死锁的危险,不过实际上系统会把进程B换出内存,重新将进程A换入内存 [也就是A进程反过来抢占了B进程的内存资源],效果也就是进程A继续执行直到完成并释放打印机,而后B进程就能够执行了)。从中可以看出由于可抢占资源可以通过重新分配资源而避免了死锁的发生,所以可抢占资源是不会发生死锁现象的。
不可抢占资源:在不引起相关计算失败的情况下,无法把它从占有它的进程处抢占过来的资源。e.g:刻录机(假设一个进程已经开始刻盘,突然将刻录机分配给另一个进程,那么将划坏CD盘,所以任何时候刻录机都是不能被抢占的)
死锁:当多个进程需要排他性的访问多个资源,且其所需要的资源在同一时间属于不同进程且还是不可抢占资源的时候,此时相关进程就会一直请求对应资源但得不到从而一直阻塞下去,这就是死锁现象。
*除了硬件机器与I/O设备之外,别的情况也可能引起死锁,比如一个数据库系统中,为了避免竞争可对若干记录加锁,假设进程A对记录R1加锁而进程B岁记录R2加锁,接着他们又各自试着加锁对方的记录,此时也会发生死锁
注:关于GIL(global interpreter lock),可参见这篇文章:http://www.dabeaz.com/python/UnderstandingGIL.pdf
二:Threading模块
2.1.threading.Thread对象【创建线程的主要对象】:
方法:start():启动线程
run():启动线程后自动调用的方法
join([timeout]):等待到被调用的线程终止
is_alive():返回线程活动状态
属性:name:线程名
ident:线程ID号
daemon:后台标志
2.2.创建线程的方法:
1:实例化threading.Thread对象
ths = threading.Thread( target = None, name = None, args = (), kwarg = {} )
传入函数名 线程名 函数的参数
2:继承threading中的Thread对象后再实例化并启动
2.3.以不同的线程类型分:
令:t = threading.Thread(target=dmn...),即是t为一个线程
2.3.1.独立线程:就是最简单的独立单线程
2.3.2.线程等待:t.join([timeout]),放到start()后,表明t线程执行完后(或是指定时间后)才轮到下一个线程【若是因为指定时间的话还会跳回t线程】
1 #coding:utf-8 2 import threading, time 3 class MyThread(threading.Thread): 4 5 def run(self): 6 for i in range(40): 7 print() #若是t线程在执行时就是打印换行 8 time.sleep(0.1) 9 10 if __name__ == "__main__": 11 t = MyThread() 12 t.start() 13 **t.join()** 14 for i in range(10): #此部分是主线程执行的,也就是说此程序有主线程与t线程两个线程 15 print("main:", i) 16 time.sleep(0.1) 17 18 #最后会在打印完了换行后才打印0到9的“main:...”, 说明t线程执行完了后主线程才执行的