进程
进程就是一段程序执行的过程。切换不同的进程实际上是进行上下文切换。
进程有三种状态:就绪、运行和阻塞。
就绪态:就是获取了除CPU之外的所有资源,只要处理器分配资源就可以马上执行
运行态:获得了处理器分配的资源,程序开始执行
阻塞态:当程序条件不够时,需要等待条件满足时才可以执行,如等待I/O操作时候,此刻的状态就叫做阻塞态。
线程
在一个进程中可以有多个线程,一个进程中至少有一个线程。
多线程
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统效率。线程是在同一时间需要完成多项任务的时候实现的。
进程和线程的区别
1、一个程序至少有一个进程,一个进程至少有一个线程
2、线程的划分尺度小于进程,使得多线程程序并发性高
3、进程在执行过程中拥有独立的内存单元,而多个线程共享内存单元,从而极大的提高了程序的运行效率
4、每个独立的线程有一个程序运行的入口,顺序执行序列和程序执行出口,但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5、多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。
创建多线程
import threading
import time
def run(name):
print(name,"线程执行了")
time.sleep(5)
t1 = threading.Thread(target=run,args=("t1",))#创建线程实例
t2 = threading.Thread(target=run,args=("t2",))
t1.start()#启动线程
t2.start()
一个简单的线程就创建并启动了
主线程和子线程
*程序执行时,程序本身就是一个线程,叫主线程
*手动创建的线程叫子线程
*主线程的执行中不会等待子线程执行完毕,就会执行后面代码
def run(name):
print(name,"线程执行了")
time.sleep(5)
t1 = threading.Thread(target=run,args=("t1",))#创建线程实例
t2 = threading.Thread(target=run,args=("t2",))
t1.start()#启动线程
t2.start()
#添加join()
t1.join()
t2.join()
print("执行完毕")
还是上面这段代码,在最后加一句打印语句执行完毕,讲道理来说应该是t1,t2两个线程执行完毕后停顿5秒在执行打印语句“执行完毕”,但是实际的结果并不是这样,原因就是上面三句打*号的语句。那如何解决这个问题呢?很简单,在t2.start()后加上t1.join()和t2.join()两句代码就解决了。join()方法的意思是等待子线程执行完毕之后再执行主线程的内容。
线程锁
import threading
num=100
lock=threading.Lock()#创建一个线程锁
def run(name):
lock.acquire()#设置锁
global num
num=num-1
print("线程",num,"执行:",num)
lock.release()#释放锁
for iin range(100):
t=threading.Thread(target=run,args=(i+1,))
t.start()
以上这段代码创建了100个线程,每次创建num都减去1,但是运行时不会按照顺序,会出现错乱现象。为了防止这个现象,加上线程锁就可以解决。参考注释部分代码
全局解释器锁(GIL)
全局解释器锁保证python中同一时间只运行一个线程,不管系统CPU有几个核心,本意上是为了实现数据的安全,实际上是造成了CPU的浪费,影响了程序的执行效率,是弊大于利。如何解决GIL带来的这个问题呢?使用多进程可以解决。
多进程
from multiprocessingimport Process
import time
def run(name):
print(name,"进程执行了")
time.sleep(5)
if __name__ =='__main__':
#创建多进程
p1=Process(target=run,args=("p1",))
p2=Process(target=run,args=("p2",))
p3=Process(target=run,args=("p3",))
p4=Process(target=run,args=("p4",))
p5=Process(target=run,args=("p5",))
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
以上代码实现了一个简单的多进程,多进程可以真正实现同一时间多个任务并行,前提是CPU是多核,单核的就没有意义。还有一点要提醒大家注意的是Windows系统执行时要加上if __name__ =='__main__':这句代码,这句代码的意思是在当前模块运行才会执行,外部导入模块则不会执行,否则会报错无法运行,linux则不用加。