进程与线程的区别
进程是资源分配的最小单位,线程是CPU调度的最小单位
线程在进程下行进;线程无地址空间,它包括在进程的地址空间里;
一个进程可以包含多个线程;
不同进程间数据很难共享;
同一进程下不同线程间数据很易共享;
进程要比线程消耗更多的计算机资源;
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉;
进程可以拓展到多机,进程最多适合多核;
进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存;
进程使用的内存地址可以限定使用量;
函数调用加括号和不加括号的区别
函数加括号是指对此函数的调用
函数不加括号是指调用函数本身(的内存地址)
import time def task(): print(time.time()) task() print(task()) print(task)
1637464945.9630685 1637464945.9630685 None <function task at 0x0000023412191E18>
线程执行
两线程同时执行,但是时间差的代码执行不会等两个线程直线完之后在执行,而是和线程同时执行。
import threading import time def task(): print(time.time()) time.sleep(5) print("---------------------------------") def main(): start_time = time.time() thread1 = threading.Thread(target=task) thread2 = threading.Thread(target=task) thread1.start() thread2.start() end_time = time.time() print(end_time-start_time) #时间差的代码 if __name__ == '__main__': main()
1637465538.072043
1637465538.072043
0.0009961128234863281
---------------------------------
---------------------------------
在两个线程后面,加了join()之后,线程1和线程2执行完之后,再执行主线程。
import threading import time def task(): print(time.time()) time.sleep(5) print("---------------------------------") def main(): start_time = time.time() thread1 = threading.Thread(target=task) thread2 = threading.Thread(target=task) thread1.start() thread2.start() thread1.join() #让其他线程等待自己执行完成 thread2.join() end_time = time.time() print(end_time-start_time) if __name__ == '__main__': main()
1637465832.2290647 1637465832.2290647 --------------------------------- --------------------------------- 5.008389472961426
GIL锁 【全局解释器锁】在同一时刻,只能有一个线程运行。每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行,目的是解决多线程同时竞争程序中的全局变量而出现的线程安全问题。它并不是python语言的特性,仅仅是由于历史的原因在CPython解释器中难以移除,因为python语言运行环境大部分默认在CPython解释器中。
GIL面试题参考答案:
Python语言和GIL没有什么关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100。
Python使用多进程是可以利用多核的CPU资源的。
多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁。
————————————————
原文链接:https://blog.csdn.net/qq_40808154/article/details/89398076
总结下来:如果不用sleep函数,其他方法执行的话,会发现,线程运行顺序是等第一个线程运行完之后,在运行第二个线程的,统一进程内,只能运行一个线程
python 可调用对象:
用户自定义的函数:使用def语句或者lambda表达式创建的函数。
内置函数:使用C语言实现的函数,如len、sum或者time.strftime
内置方法:使用C语言实现的方法,如dict.get()
类方法:在类的定义体中定义的函数
类:在调用类时会运行类的__new__方法创建一个实例,然后运行__init__方法,初始化实例,最后把实例返回给调用方。Python中没有new运算符,所以调用类相当于调用函数。
类的实例:如果类定义了__call__方法,那么它的实例可以作为函数进行调用。并且__call__方法可以进行自定义重写。
生成器函数:使用yield关键字的函数或方法。调用生成器函数返回的是生成器对象。