一. python的线程
多线程:多线程可以共享本进程中的数据,但是不稳定,如果服务器用多线程来处理可能会因为其中一个线程崩了,而服务器就挂了,相反,多进程一般一个子进程错误,不会导致所有子进程都错误,但是主进程挂了,其他照样都挂。
对于python的多线程实现,其实只是一个线程在跑,不断地进行切换,不是真正的多线程,即使遇到多核cpu,多核cpu只有一个核区发挥其作用,因此,python的多线程用于io密集型的操作中,而在cpu密集型的程序,反而变得更慢。
起因为GIL:
GIL:In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
之所以有GIL这个大坑主要是因为线程安全,python在多线程中为了使其能够实现线程安全,提高其性能,即在多线程下,不会对全局变量或者静态变量进行污染。通过这样的一个锁,使拥有GIL的线程才能运行,在提高性能的同时,效率却下降了,这是Python在效率和性能间的权衡。
可能出现的问题:
1. Python中释放GIL会触发操作系统的一次线程调度,激起后的线程等待被分配GIL,但是,再多核CPU中,如果该线程在其他核心,因为release gil和acquire gil之间的间隙可以说是很短的,大部分情况下很可能刚释放GIL的线程又再次得到GIL。
2. 而这样,被唤醒的线程只能等待,这也一定程度上影响了IO线程(接收到消息时,有一个CPU密集型的线程仍在不断的释放,再次得到GIL)。此外,Python的线程安全并不是绝对安全,怎么感觉GIL还是没什么用,有时候还是会出错,如下面程序:
import threading
import time
t_obj = []
lock = threading.Lock()
num = 0
def run():
global num
#lock.acquire()
num += 1
time.sleep(1)
num += 1
#lock.release()
for i in range(100):
t = threading.Thread(target = run)
t_obj.append(t)
t.start()
for i in t_obj:
t.join()
print(num)
可以发现,有时候跑出来的结果比正常值小,解决方法是用Python的一个互斥锁(线程锁),这样GIL的意义我就不太清楚是什么了
只有lock释放的时候,另外一个线程才能启动。出现结果为198的原因如下:
Python的GIL释放算法是基于pcode(通过计算线程执行的微代码数量来进行GIL的切换),还是基于时间的切换。都有一个可能,程序在运行一半时被强行切换,此时Python将其数据暂时保存在缓冲区中,去执行另外一个线程,而没来得及数据的更新,另一个线程取的数据是没有++过的,而两个线程结果返回到内存时,其实可以说只进行了一次操作。(这里有一个猜想,可能被中途中断保存到缓冲区的线程的优先级比较高,不然的话结果可能偏差很大)
其实CPYTHON中已经有了一个pthread线程调度算法,这是c语言自己的一个线程调用机制,应该可以理解为GIL是在pthread的上层对其进行管理。
解决方法:
1. 改进Reworking the GIL
– 将切换颗粒度从基于opcode计数改成基于时间片计数(不知道其作用在哪)
– 避免最近一次释放GIL锁的线程再次被立即调度
– 新增线程优先级功能(高优先级线程可以迫使其他线程释放所持有的GIL锁)
2. 用multiprocess替代Thread,缺点为数据共享时将很浪费资源,要通过一个pickle
3. 用其他解析器,其他解析器有的虽然不用GIL,但是其不是用c语言写的,c语言多模块的优势就体现不了(暂时无体会)
出处:
1.https://www.zhihu.com/question/23474039 Python多线程的妥协
2.http://blog.youkuaiyun.com/q_l_s/article/details/51538039 IO密集型与CPU密集型,多线程与多进程
3.https://www.zhihu.com/question/21486706 余天升 编译性语言和解释性语言
4.http://python.jobbole.com/81822/ GIL(重点)
5.https://wiki.python.org/moin/GlobalInterpreterLock (英)GIL