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))
 
#多线程共享全局变量
 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_num
12 # for i in range(1000000):
13 # global_num += 1
14 # 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 += 1
12 lock.release()
13 print("test1", global_num)
14
15
16 def test2():
17 global global_num
18 lock.acquire()
19 for i in range(1000000):
20 global_num += 1
21 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密集型的代码里,用多线程就很合适
 

python多线程和GIL全局解释器锁的更多相关文章

  1. Python并发编程-GIL全局解释器锁

    Python并发编程-GIL全局解释器锁 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.GIL全局解释器锁概述 CPython 在解释器进程级别有一把锁,叫做GIL,即全局解释 ...

  2. 网络编程-Python高级语法-GIL全局解释器锁

    知识点:GIL全局解释器锁其实和Python没有任何关系,是由于当初编写Python解释器时留下的,它只对多线程有影响,GIL保证同一时刻只有一个线程在运行,即使是多核配置电脑,同一时刻也只会让一个线 ...

  3. Python中对于GIL全局解释器锁的一点理解

    GIL全局解释器锁 python最初开发时,开发人只考虑到了单核CPU的,为解决多线程运算之间的数据完整性和状态同步选择了加锁的方式.即GIL锁. 而目前的CPU都有多个核心,在运行python的某个 ...

  4. 进程、线程与GIL全局解释器锁详解

    进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...

  5. [Python 多线程] GIL全局解释器锁 (十三)

    Queue 标准库queue模块,提供FIFO(先进先出)的Queue.LIFO(后进先出)的队列.优先队列. Queue类是线程安全的,适用于多线程间安全的交换数据.内部使用了Lock和Condit ...

  6. python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程

    GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...

  7. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  8. python 并发编程 多线程 GIL全局解释器锁基本概念

    首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码. ...

  9. GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论

    昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...

随机推荐

  1. 高可用K8S构建3master+3node+keepalived+haproxy

    视频地址:https://www.bilibili.com/video/BV1w4411y7Go?p=66 所需安装包在视频评论区 安装准备 系统: CentOS-7-x86_64-Minimal-1 ...

  2. sqoop用法之mysql与hive数据导入导出

    目录 一. Sqoop介绍 二. Mysql 数据导入到 Hive 三. Hive数据导入到Mysql 四. mysql数据增量导入hive 1. 基于递增列Append导入 1). 创建hive表 ...

  3. wildfly 21的domain配置

    目录 简介 wildfly模式简介 domain controller的配置 Host controller的配置文件 忽略域范围的资源 Server groups Servers 总结 简介 wil ...

  4. Flutter ListTile - Flutter每周一组件

    该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://github.com/xj124456/fl ...

  5. Impala的count(distinct QUESTION_ID) 与ndv(QUESTION_ID)

    在impala中,一个select执行多个count(distinct col)会报错,举例: select C_DEPT2, count(distinct QUESTION_BUSI_ID) as ...

  6. 使用ajax请求上传多个或者多个附件

    jsp页面 <%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML> ...

  7. 【超级经典】程序员装B指南(转)

    一.准备工作   "工欲善其事必先利其器." 1.电脑不一定要配置高,但是双屏是必须的,越大越好,能一个横屏一个竖屏更好.一个用来查资料,一个用来写代码.总之要显得信息量很大,效率 ...

  8. [简单-剑指 Offer 53 - II. 0~n-1中缺失的数字]

    [简单-剑指 Offer 53 - II. 0-n-1中缺失的数字] 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0-n-1之内.在范围0-n-1内的n个数字中有且只有一 ...

  9. Java中几种常见的循环

    多重if_else: package com.dengchaoqun.ht; public class Double_For02 { /** * * 打印乘法表 */ public static vo ...

  10. Redis学习之路(三)常用命令总结

    一.集群 查看Redis集群有多少个库 192.168.200.100:7001> config get databases 1) "databases" 2) " ...