python学习第三十节(互斥锁,死锁,迭代锁+信号量)

python多线程概念的讲解:

#1、线程与进程的区别是什么?(怎么理解怎么写)
'''
进程是程序运行的状态和过程。
进程会占用内存中的一块空间,消耗资源。
每个进程最少会有一个线程(主线程),可以有多个线程。
pyyhon在运行的过程中最多只能有一个线程调用CPU资源,那是因为在每个进程前面有GIL全局解释器锁。
多个线程通过全局解释器锁是靠操作系统分配的,同一时刻只能有一个线程获得CPU资源 ,如果该线程
遇到IO操作,操作系统会将CPU分配给别的线程做运算,直到该线程IO操作结束继续计算。
如果多线程计算过程调用了全局变量就需要注意线程安全的问题,该问题只有多线程运算会遇到,
线程安全的问题会直接影响程序运行结果。
线程安全可以用互斥锁、迭代锁来解决。互斥锁相当于用户设置一个锁控制线程调用CPU资源,在一个线程调用CPU的过程中
即便遇到IO操作由于锁的原因也不会将资源分配给其他线程使用,起到了串行计算的作用,由于互斥锁设置方便,可以自主
设置锁住的位置和解锁的位置所以比单纯的单线程用JOIN的方式效率更高。
由于互斥锁功能相对简单,不恰当的使用会导致死锁现象,所以有了迭代锁的概念,用treading.RLock()控制,
起到线程串行的作用,不会导致线程安全问题。
'''
# 2、在 Python 中,哪一种多线程的程序表现得更好,I/O 密集型的还是计算 密集型的?
'''
在python中多线程更适用于IO密集型操作,并不适用于计算密集型。
由于python的机制是当一个线程遇到IO操作的时候会将CPU资源给下一个线程使用,直到IO操作结束才会继续调用CPU资源。
这样的机制导致PYTHON更适用于IO密集型,而计算密集型在多个线程的时候会处于并发的状态,当一个线程计算一半的时候将
CPU资源分配给其他的线程计算,上一个计算的结果还需要保存起来,占用资源,另外多个线程计算在切换的过程中是消耗资源的,
并且计算的效率并没有提升反而有下降,故并不建议用python多线程运行计算密集型的代码。
'''

进程是程序运行的状态和过程。

son类print父类方法,执行失败。因为子类在重写父类方法

 ,但没有num参数。

线程的另一种使用方法,相当于换一种方式执行函数。
t1.start()之所以能运行run方法是因为父类里有一个run方法,现在是将其重写了。在python
thread类里有一个run方法。

 

 函数。模块。类。这三个拥有自己的局部空间。

 

定义一个空列表
实例化
将对象加到列表
循环start
GIL(全局解释器锁)
多个线程无法在同一时刻执行。
坏处是无法使用多核。

gil锁为了管理内存而存在,对于用户并没有用。
gil锁在每个进程前面加一把锁,每个锁只有一个出口让线程出去。
线程有锁,进程开销太大(每开一个进程就要开辟一段内存空间),只能携程。

守护进程一般的应用场景是监听,因为守护进程会等主进程结束才结束。主进程结束守护进程也结束。

线程安全
在线程去了内存中的变量如果去cpu计算的时候,遇到IO阻塞,其他线程会去取内存中的变量再去CPU计算,继续几次之后,由于IO阻塞结束之后,继续计算,最后计算的结果不一定准确,所以一定要注意IO阻塞。

r=threading.LOCK() 线程锁

上图这么写不行,因为循环结束t等于最后一个值,前面的没有了,循环外面写Join只能最后一个是join
需要在写一个循环将每次都join,如下图

线程安全问题。
当线程涉及到全局变量的时候就会出现线程安全问题。
用互斥锁虽然在多线程的位置是串行,但是在解锁的位置如果在得当的位置,下面无序再串行。
而如果不用多线程,则所有IO操作都要串行,时间慢很多。


死锁:就是两个线程在等待对方释放一个锁来运行代码的现象。


这个互斥锁在加锁的相关位置是相当于串行处理,不加锁的位置没有影响。
这个互斥锁和join的区别是,互斥锁只在加锁的位置影响,而join影响整个程序。

死锁,一般的lock.acquire,大锁套小锁之后小锁套大锁,下一个线程会矛盾,之后卡死。

Rlock.acquire() 递归锁,

如果Rlock为0 才可以有新的线程进入,进入之后变1 在进入之后+1 为2 ,release之后-1
遇到信息安全的问题,只能加锁,并且串行计算,这是唯一的方法。

解决死锁的方法:

 信号量 :限制线程数量的。完成一个进入一个。也是一种锁。

原文地址:https://www.cnblogs.com/ArmoredTitan/p/7200838.html