博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python多线程和GIL全局解释器锁
阅读量:5107 次
发布时间:2019-06-13

本文共 3931 字,大约阅读时间需要 13 分钟。

1、线程

    线程被称为轻量级进程,是最小执行单元,系统调度的单位。线程切换需要的资源一般,效率一般。 

2、多线程

        在单个程序中同时运行多个线程完成不同的工作,称为多线程

3、并发:

    操作系统同时执行几个程序,这几个程序都由一个cpu处理,但在一个时刻点上只有一个程序在cpu上处理

4、并行:

    操作系统同时执行2个程序,但是有两个cpu,每个cpu处理一个程序,叫并行

5、串行: 

    是指的我们从事某项工作是一个步骤一个步骤去实施 
 

一、多线程

#python3是假的多线程,它不是真真正正的并行,其实就是串行,只不过利用了cpu上下文的切换而已
1 mport threading 2 import time 3 # def test1(): 4 #     for i in range(10): 5 #         time.sleep(1)             #睡1s 6 #         print('test1=========>%s' % i) 7 # 8 # 9 # def test2():10 #     for i in range(10):11 #         time.sleep(1)12 #         print('test2=========>%s' % i)13 #14 # t1 = threading.Thread(target=test1)    #定义一个线程  target=函数名15 # t2 = threading.Thread(target=test2)16 # t1.start()        #开启线程17 # t2.start()18 # test1()19 # test2()
# 多线程是无序的,并发的
因为在启动一个线程时,线程不会立即执行,而是等待cpu的资源调度。
1 # def test1(n):2 #     time.sleep(1)3 #     print('task', n)4 # for i in range(10):5 #     t = threading.Thread(target=test1,args=('t-%s' % i,))  #args= 后接输出结果  末尾必须加 “ , ” 号6 #     t.start()
 
#计算并发所用的时间
1   2 # import threading 3 # import time 4 # def dest(n): 5 #     time.sleep(1) 6 #     print('this is running====>%s' %n) 7 # l = []     #定义一个空列表 8 # start = time.time()     #开始的时间 9 # for i in range(10):        #10个进程10 #     t = threading.Thread(target=dest,args=(i,))    11 #     t.start()12 #     l.append(t)      #把线程执行时间加入到列表13 # for g in l:       14 #     g.join()            #等待全部线程执行完毕15 # end = time.time()            #执行结束时间16 # print('time',(end-start))   #执行结束时间 - 开始执行的时间
 
1 import threading 2 import time 3 def test1(n): 4     time.sleep(1) 5     print('test1====>%s' %n) 6 def test2(n): 7     time.sleep(2) 8     print('test2====>%s' %n) 9 start = time.time()10 l = []11 t1 =  threading.Thread(target=test1,args=(1,))12 t2 = threading.Thread(target=test2,args=(2,))13 t1.start()14 t2.start()15 l.append(t1)16 l.append(t2)17 for i in l:18     i.join()19 end = time.time()20 print('time',(end - start))
View Code
 
#多线程共享全局变量
1 # g_num = 0 2 # def update(): 3 #     global g_num    #global声明全局变量 4 #     for i in range(10): 5 #         g_num += 1 6 # 7 # def reader(): 8 #     global g_num 9 #     print(g_num)10 #11 # t1 = threading.Thread(target=update)12 # t2 = threading.Thread(target=reader)13 # t1.start()14 # t2.start()15

二、GIL全局解释器锁

        只有获得GIL锁的线程才能真正在cpu上运行。所以,多线程在python中只能交替执行,即使100个线程跑在100核cpu上,也只能用到1核。
1   2 # import threading 3 # global_num = 0 4 # def test1(): 5 #     global global_num        #global声明全局变量 6 #     for i in range(1000000): 7 #         global_num += 1 8 #     print("test1", global_num,threading.current_thread()) 9 #10 # def test2():11 #     global global_num12 #     for i in range(1000000):13 #         global_num += 114 #     print("test2", global_num,threading.current_thread())15 # t1 = threading.Thread(target=test1)16 # t2 = threading.Thread(target=test2)17 # t1.start()18 # t2.start()19 # print(global_num)
结果说明:每次执行结果都不一样,原因是python从上往下执行,主线程走的快,当主线程走到最后print打印结果的时候,test1 test2的count++还在继续执行,所以第一行打印出来的是它们在执行count++过程中的某一个值,至于test1和test2的值不是100w和200w,因为cpu没有足够的时间去进行count++就释放锁提交了
 

#互斥锁

以上出现的结果是随机的,并非我们想要的,所以要加入互斥锁。
互斥锁:
常用来防止两个进程或线程同一时刻访问相同的共享资源, 如果一个线程锁定了一个互斥量,在它解除锁定之前没有其他线程可以锁定这个互斥量。
1 import threading 2 import time 3 global_num = 0 4   5 lock = threading.Lock()           #互斥锁 6   7 def test1(): 8     global global_num 9     lock.acquire()10     for i in range(1000000):11         global_num += 112     lock.release()13     print("test1", global_num)14  15  16 def test2():17     global global_num18     lock.acquire()19     for i in range(1000000):20         global_num += 121     lock.release()22     print("test2", global_num)23  24 t1 = threading.Thread(target=test1)25 t2 = threading.Thread(target=test2)26 start_time = time.time()27  28 t1.start()29 t2.start()30 t1.join()31 t2.join()32 print(global_num)
加上互斥锁之后,test1线程执行完才释放锁提交,让test2线程拿到共享资源继续执行,要想结果是200w,就必须是主线程等子线程执行完之后才执行print。
 
#只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就很合适
 

转载于:https://www.cnblogs.com/heiguu/p/10049537.html

你可能感兴趣的文章
HTML5——新表单元素 表单属性 语义元素
查看>>
CSS3—— 分页 框大小 弹性盒子 多媒体查询 多媒体查询实例
查看>>
使用反射获取Android中隐藏的方法
查看>>
【原创】Leetcode -- Reverse Linked List II -- 代码随笔(备忘)
查看>>
人脸识别技术开发人证比对访客系统
查看>>
Android之人脸识别
查看>>
HDU 5340——Three Palindromes——————【manacher处理回文串】
查看>>
二叉树的下一个节点
查看>>
Nginx配置文件详细说明
查看>>
遇到的Mysql的一个坑
查看>>
AC日记——「HNOI2017」单旋 LiBreOJ 2018
查看>>
vue总结
查看>>
真机调试的准备工作介绍
查看>>
(笔记)Linux内核学习(十一)之I/O层和I/O调度机制
查看>>
IIS注册 net环境
查看>>
P1242 新汉诺塔
查看>>
页面元素解绑click事件
查看>>
数据移植实验
查看>>
输入任意个数字求和的小程序
查看>>
How Many Tables
查看>>