GIL与线程进程小知识点
一 、GIL全局解释器
GIL是一个互斥锁:保证数据的安全(以牺牲效率来换取数据的安全)
阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发)
并发:看起来像同时进行的
GIL全局解释器存在的原因是因为Cpython解释器的内存管理不是线程安全的
垃圾回收机制
1.引用计数
2.标记清除
3.分代回收

同一个进程下的多个线程不能实现并行但是能够实现并发,多个进程下的线程能够实现并行
问题:python多线程是不是就没有用了呢?
四个任务:计算密集的任务 每个任务耗时10s
单核情况下:
多线程好一点,消耗的资源少一点
多核情况下:
开四个进程:10s多一点
开四个线程:40s多一点
四个任务:IO密集的任务 每个任务io 10s
单核情况下:
多线程好一点
多核情况下:
多线程好一点
多线程和多进程都有自己的优点,要根据项目需求合理选择
# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=
for i in range():
res*=i if __name__ == '__main__':
l=[]
print(os.cpu_count()) # 本机为4核
start=time.time()
for i in range():
# p=Process(target=work) #耗时13.
p=Thread(target=work) #耗时25.
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
# IO密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time def work():
time.sleep() if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range():
p=Process(target=work) #耗时4.
# p=Thread(target=work) #耗时2.
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
二 、 GIL与普通锁对比
代码
from threading import Thread,Lock
import time mutex = Lock() n = 100 def task():
global n
mutex.acquire()
tmp = n
time.sleep(0.1)
n = tmp - 1
mutex.release() t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t) for t in t_list:
t.join() print(n) -->> 0
对于不同的数据,要想保证安全,需要加不同的锁处理
GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程
保证的是同一个进程下多个线程之间的安全
三 、死锁与递归锁(了解)
代码演示
from threading import Thread,Lock,RLock
import time """
自定义锁一次acquire必须对应一次release,不能连续acquire
递归锁可以连续的acquire,每acquire一次计数加一:针对的是第一个抢到我的人
""" #
# mutexA = Lock()
# mutexB = Lock()
mutexA = mutexB = RLock() # 抢锁之后会有一个计数 抢一次计数加一 针对的是第一个抢到我的人 class MyThread(Thread):
def run(self):
self.func1()
self.func2() def func1(self):
mutexA.acquire()
print('%s 抢到A锁了'%self.name)
mutexB.acquire()
print('%s 抢到B锁了' % self.name)
mutexB.release()
print('%s 释放了B锁'%self.name)
mutexA.release()
print('%s 释放了A锁'%self.name) def func2(self):
mutexB.acquire()
print('%s 抢到了B锁'%self.name)
time.sleep(1)
mutexA.acquire()
print('%s 抢到A锁了' % self.name)
mutexA.release()
print('%s 释放了A锁' % self.name)
mutexB.release()
print('%s 释放了B锁' % self.name) for i in range(100):
t = MyThread()
t.start()
四 、 信号量(了解)
代码演示
from threading import Thread,Semaphore
import time
import random
sm = Semaphore(5) # 五个厕所五把锁
# 跟你普通的互斥锁区别在于,普通的互斥锁是独立卫生间,所有人抢一把锁
# 信号量 公共卫生间 有多个坑,所有人抢多把锁 def task(name):
sm.acquire()
print('%s正在蹲坑'%name)
# 模拟蹲坑耗时
time.sleep(random.randint(1,5))
sm.release() if __name__ == '__main__':
for i in range(20):
t = Thread(target=task,args=('伞兵%s号'%i,))
t.start()
五 、 event事件(了解)
例子:
from threading import Event,Thread
import time
import random event = Event() def light():
print('红灯亮着!')
time.sleep(3)
event.set() # 解除阻塞,给我的event发了一个信号
print('绿灯亮了!') def car(i):
print('%s 正在等红灯了'%i)
event.wait() # 阻塞
print('%s 加油门飙车了'%i) t1 = Thread(target=light)
t1.start() for i in range(10):
t = Thread(target=car,args=(i,))
t.start()
六 、线程Queue(了解)
import queue # 1.普通q
# 2.先进后出q
# 3.优先级q # q=queue.Queue(3)
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())
# print(q.get())
# print(q.get()) # q = queue.LifoQueue(5)
# q.put(1)
# q.put(2)
# q.put(3)
# q.put(4)
# print(q.get()) # 优先级q
# q = queue.PriorityQueue()
# q.put((10,'a'))
# q.put((-1,'b'))
# q.put((100,'c'))
# print(q.get())
# print(q.get())
# print(q.get())
GIL与线程进程小知识点的更多相关文章
- GIL锁、进程池与线程池
1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...
- CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步
一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示 ...
- GIL锁和进程/线程池
GIL锁 1.GIL锁 全局解释器锁,就是一个把互斥锁,将并发变成串行,同一时刻只能有一个线程使用共享资源,牺牲效率,保证数据安全,也让程序员避免自己一个个加锁,减轻开发负担 带来的问题 感觉单核处理 ...
- 文成小盆友python-num11-(1) 线程 进程 协程
本节主要内容 线程补充 进程 协程 一.线程补充 1.两种使用方法 这里主要涉及两种使用方法,一种为直接使用,一种为定义自己的类然后继承使用如下: 直接使用如下: import threading d ...
- 13 并发编程-(线程)-异步调用与回调机制&进程池线程池小练习
#提交任务的两种方式 #1.同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果,再执行下一行代码,导致程序是串行执行 一.提交任务的两种方式 1.同步调用:提交任务后,就在原地等待任务完毕,拿 ...
- GIL 线程/进程池 同步异步
GIL 什么是GIL 全局解释器锁,本质是一把互斥锁,是加在cpython解释器上的一把锁, 同一个进程内的所有线程需要先抢到GIL锁,才能执行python代码 为什么要有GIL cpython解释器 ...
- python之线程进程协成
线程与进程 什么是线程 线程是进程一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个线程的 ...
- Python之线程&进程
线程: 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. thr ...
- python_21_线程+进程+协程
python_线程_进程_协程 什么是线程? -- os能够进行运算调度的最小单位,被包含在进程之中,是一串指令的集合 -- 每个线程都是独立的,可以访问同一进程下所有的资源 什么是进程? -- 每个 ...
随机推荐
- mysql中int长度的意义 int(0)
问题: mysql的字段,unsigned int(3), 和unsinged int(6), 能存储的数值范围是否相同.如果不同,分别是多大?int(0) 能存多少位数字? 不同,int(3)最多显 ...
- vim卡死
使用vim时,如果你不小心按了 Ctrl + s后,你会发现不能输入任何东西了,像死掉了一般,其实vim并没有死掉,这时vim只是停止向终端输出而已,要想退出这种状态,只需按Ctrl + q 即可恢复 ...
- flutter 主页面底部导航栏实现以及主题风格设置
import 'package:flutter/material.dart'; import 'package:flutter_app/bottom_navigation_widget.dart'; ...
- Flink FileSink 自定义输出路径——StreamingFileSink、BucketingSink 和 StreamingFileSink简单比较
接上篇:Flink FileSink 自定义输出路径——BucketingSink 上篇使用BucketingSink 实现了自定义输出路径,现在来看看 StreamingFileSink( 据说是S ...
- linux信号量例子
semaphore.h 提供的是 POSIX 标准定义的 semaphore 接口,而 sys/sem.h 里 提供的是符合 System V 标准的 semaphore接口 (semget, sem ...
- python解包
概念 python的解包可以这样来理解:把元素给拆分并把其赋值给自己所需要的变量,因此元素应该是一个可迭代对象. 形式 简单版本 下面展示的是解包的基本形式,根据长度赋值给对应多的变量. name_l ...
- [概率DP][消元法][CF24D]损坏的机器人
Description 有一只坏了的机器人站在一个\(n\times m\)的网格里,初始位置在\((x,y)\).现在每个单位时间内它会随机选左右下三个方向走,如果它随机的方向会走出网格就不会往这个 ...
- javascript bom操作
BOM BOM介绍 全称 Browser Object Mode 浏览器对象模式 操作浏览器的API接口.比如浏览器自动滚动 Windows对象的顶层部分是BOM的顶层(核心)对象,所有的对象都是通过 ...
- STM32 MDK摘记
题记:这人是越懒越懒,记性也也来越差,前段时间改了个链接文件,今天想用,竟然忘了咋写....还是勤记记吧... 随时更新,笔记帖. 不喜勿喷! 1,关于MDK链接文件宏的定义 #! armcc -E ...
- Beginning Linux Programming 学习--chapter 1 Getting start--What's linux,GNU,HeaderFiles, Libraries
"文明的建立的不是机器而是思想" -- 托尔斯泰 Linux truly become a viable operating system, especially in the s ...