在使用python运行同样的东西的时候,有时候比java和c慢很多,在有些情况下python 的运行速度比c慢100-200倍。
具体是什么原因,其实原因不过有两点:边解释边运行和GIL(全局解释器锁)
边解释边运行
因为pyhon 是一个动态语言,不像java在先编译java文件为class文件,然后运行编译后class的程序。它是一边运行文件,一边将其某行程序编译成计算器识别的二进制,然后再运行,而且再第二次运行的时候还是这样。所以会慢。
GIL(全局解释器锁)
GIL 是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程运行。即使在多核cpu上运行,只要使用了GIL的解释器也只允许某一时刻只能执行一个线程。
既然有如此弊端,为什么python当初这样设计加入GIL呢?
首先要理解python对对象的管理,其对引用某一个对象的时候都是用计数器进行管理的,当其计数器为0 的时候就会释放。
比如:线程A与线程B同时引用对象obj,那么obj的计数为2,当ojb计数为0的时候就会将对象释放。但是这个时候
这样的话就会涉及到一个安全问题,如果多线程的时候引用一个对象的时候,就会出现数据安全问题。
这如果A和B在各自运行的到第二步,将obj的时候就会出现一个事情obj.conut为1,因为两个同时调用obj.conut的时候其值的确为0,同时操作的话彼此都是+1,不过都是0+1.那样的话会出现一个问题。
当A或B运行后cont为1-1等于0.那么A或者B就会释放obj,但是另一个线程再调用obj的时候发现其已经不存在,因为前面的obj已经被释放掉了。 所以引用了GIL,保证了程序数据的安全。
这个是很诡异的一件事情,因为再多线程多并发的时候为了保证程序运行的数据安全加入的锁。到后面想要摆脱的时候发现很难将其剥离。也就意味这其再设计这门语言的时候几乎已经决定了后面发展版本对其的依赖,也就是短期之内很难讲GIL这个弊端修改掉。
虽然GIL有其弊端,但是其也有很多其有的优点也不应该抹去,比如到io密集操作的时候(read。write,send,recv,ect)期间,线程会释放GIL,实现cpu和io的并行。因此如何io操作很多的时候会提升速度。但是对于需要cpu计算的时候,只会拖慢速度。
所以python引入了进程multiprocessing这个多线程机制,利用多核CPU来解决GIL对cpu密集计算的带来的问题。