一、多线程 threading模块
# 线程和进程
'''
1.线程是最小的调度单位
2.进程是最小的管理单元
3.一个进程必须至少一个线程
4.没有线程,进程也就不复存在
'''
# 多线程特点:
# python线程特点
#线程的并发是利用cpu上下文的切换(是并发,不是并行)
#多线程执行的顺序是无序的
# def test1(n): # time.sleep(1) # print('task', n) # # # t1 = threading.Thread(target=test1,args=(1,)) # # t1.start() # # for i in range(10): # t = threading.Thread(target=test1,args=('t-%s' % i,))#args:传递的参数! # t.start()
#多线程共享全局变量,但是在使用之前要声名
# g = 0 # def test1(): # global g # for i in range(10): # g += 1 # print(g) # def test2(): # global g # for i in range(10): # g += 1 # print(g) # # t1 = threading.Thread(target=test1) #target=test1:建立线程时的调用对象是test1 # t2 = threading.Thread(target=test2) # t1.start() # t2.start()
#线程是继承在进程里的,没有进程就没有线程
#GIL全局解释器锁:
当运行如下代码时,运行结果会出现错误,
import threading lock = threading.Lock() global_num = 0 def test1(): global global_num for i in range(1000000): global_num += 1 def test2(): global global_num for i in range(1000000): global_num += 1 t1 = threading.Thread(target=test1) t2 = threading.Thread(target=test2) t1.start() t2.start() t1.join() t2.join() print(global_num)
这是因为:
1,主线程运行时间太短,调用函数的t1,t2两个线程,还没有运行完,主线程就已经运行结束了
2.有GIL全局解释器存在的原因,导致错误
# lock = threading.Lock() # global_num = 0 # def test1(): # global global_num # lock.acquire() # for i in range(1000000): # global_num += 1 # lock.release() # def test2(): # global global_num # lock.acquire() # for i in range(1000000): # global_num += 1 # lock.release() # t1 = threading.Thread(target=test1) # t2 = threading.Thread(target=test2) # t1.start() # t2.start() # t1.join() # t2.join() # print(global_num)
解决的方法:
1.要使用join方法,以保证各个进程运行完
2.申请一个用户锁,将代码锁定,等到锁定的代码执行完毕之后再释放GIL全局解释器锁
#在IO密集型的代码里,适合用多线程
二、多进程 multiprocessing模块
#一个程序运行起来之后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的
#进程之间是相互独立的
#cpu密集的时候适合用多进程
import multiprocessing import time # g = 0 # def test1(n): # time.sleep(50) # global g # for i in range(10): # g += 1 # print(g) # def test2(n): # time.sleep(50) # global g # for i in range(10): # g += 1 # print(g) # # test1(1) # # test2(2) # if __name__ == '__main__': # p1 = multiprocessing.Process(target=test1,args=(1,)) # p2 = multiprocessing.Process(target=test2,args=(2,)) # p1.start() # p2.start() #进程池 # import multiprocessing # from multiprocessing import Pool # import time # import threading # g_num = 0 # def test1(n): # for i in range(n): # time.sleep(1) # print('test1', i) # # def test2(n): # for i in range(n): # time.sleep(1) # print('test2', i) # def test3(n): # for i in range(n): # time.sleep(1) # print('test3', i) # # def test4(n): # for i in range(n): # time.sleep(1) # print('test4', i) # # if __name__ == '__main__': # pool = Pool(1)#把进程声明出来,括号里不写东西说明无限制,如果写数字,就是最大的进程数 # pool.apply_async(test1,(10,))#用pool去调用函数test1,参数为10格式为(10,) # pool.apply_async(test2,(10,))#用pool去调用函数test2,参数为10格式为(10,) # pool.apply_async(test3,(10,))#用pool去调用函数test3,参数为10格式为(10,) # pool.apply_async(test4,(10,))#用pool去调用函数test4,参数为10格式为(10,) # pool.close() # close必须在join的前面 # pool.join()