标签:lock 安全 size 地址空间 targe 资源 多线程 代码 定义
相对于多进程,多线程的开销是很小的。
多线程有如下的特性:
1.在主进程下开启多个线程,每个线程都跟主进程的pid一样
2.同一进程内开启的多个线程是共享该进程地址空间的
3.守护线程会等待主线程运行完毕后被销毁
3.1、对主进程来说,运行完毕指的是主进程代码运行完毕。
主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,
3.2、对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
GIL全局解释锁
GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。
1.每次执行python程序,都会产生一个独立的进程。例如python test.py,python aaa.py,python bbb.py会产生3个不同的python进程。
2.在一个python的进程内,不仅有test.py的主线程或者由该主线程开启的其他线程,还有解释器开启的垃圾回收等解释器级别的线程,总之,所有线程都运行在这一个进程内,毫无疑问
2.1所有数据都是共享的,这其中,代码作为一种数据也是被所有线程共享的(test.py的所有代码以及Cpython解释器的所有代码)例如:test.py定义一个函数work(代码内容如下图),在进程内所有线程都能访问到work的代码,于是我们可以开启三个线程然后target都指向该代码,能访问到意味着就是可以执行。
2.2所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行,即所有的线程要想运行自己的任务,首先需要解决的是能够访问到解释器的代码。
Lock锁
锁的目的是为了保护共享的数据,同一时间只能有一个线程来修改共享的数据
保护不同的数据就应该加不同的锁。
GIL 与Lock是两把锁,保护的数据不一样,前者是解释器级别的(当然保护的就是解释器级别的数据,比如垃圾回收的数据),后者是保护用户自己开发的应用程序的数据,很明显GIL不负责这件事,只能用户自定义加锁处理,即Lock。流程大概如下图:
GIL与多线程
有了GIL的存在,同一时刻同一进程中只有一个线程被执行
对于大的cpu处理任务一般分为2种:
计算密集型和I/O密集型
在python中,对于目前的多核计算机来说,结论:
如果并发的多个任务是计算密集型:多进程效率高,如金融分析
如果并发的多个任务是I/O密集型:多线程效率高,如socket,爬虫,web
死锁现象
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些内部永远在互相等待的进程称为死锁进程。
RLock
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
标签:lock 安全 size 地址空间 targe 资源 多线程 代码 定义
原文地址:https://www.cnblogs.com/haoqirui/p/10324577.html