昨日内容

进程互斥锁

让并发变成串行,牺牲了效率,包哦挣了数据安全

mutex = Lock()
# 加锁
mutex.acquire()
# 释放锁
mutex.release()

队列

相当于在内存中开辟了一个队列空间,可以存放一堆数据,遵循“先进先出”,管道(阻塞)+锁

q = Queue()
q.put() # 添加数据,若队列满了,卡住
q.put_nowait()  # 若队列满了,报错
q.get() # 获取数据,若队列为空,卡住
q.get_nowait()  # ,若队列为空,报错
q.empty()  # 判断队列是否为空
q.full()  # 判断队列是否满了

进程间通信

进程间数据不共享,可以通过队列实现通信

生产者与消费者模型

生产者:生产数据的

消费者:使用数据的

目的:通过队列来实现该模型,解决供需不平衡问题

线程

什么是线程

进程:执行单位

线程:执行单位

注意:只要开启一个进程就会有一个线程,会在进程结束时,一并销毁

为什么使用线程

节省内存资源

  • 开启线程

    1. 开辟一个新的内存空间
    2. 会自带一个主线程
  • 开启线程
    1. 一个进程可以开启多个线程
    2. 开启线程的资源远远小于进程

创建线程的两种方式

# 创建方式1
from threading import Thread
def task():
    pass

t = Thread(target = task)
t.start()

# 创建方式2
class MyThread(Thread):
    def run():
        pass

t= MyThread()
t.start()

线程对象的属性

current_thread().name  # 获取当前线程名
enumerate()  # 获取当前所有线程对象
activeCount()  # 获取当前执行线程个数
is_alive()  # 判断线程是否存活

线程互斥锁

from threading import Thread
mutex = Lock()
mutex.acquire()
# 被锁线程
mutex.release(

今日内容

GIL全局解释器锁

基于Cpython来研究GIL

  1. GIL本质上是一个互斥锁
  2. 阻止同一个进程下多个线程同时执行,即单个进程下的多个线程不能并行,只能并发
  3. GIL的存在是为了保证线程安全(垃圾回收机制)

注意:多个线程过来执行,一旦遇到IO操作,会立马释放GIL全局解释器锁,

from threading import Thread
import time

number = 100

def task():
    global number
    number2 = number
    time.sleep(1)
    nunmer = number2 -1

for i in range(100):
    t = Thread(target = task)
    t.start()

多线程的作用

计算密集型

单核情况下,优先使用多线程

多核情况下,优先使用多进程

总结:现在大多数电脑都是多核,因此计算密集型使用多进程

from multiprocessing import Process
from threading import  Thread
import os,time

def work():
    res = 0
    for i in range(100000000):
        res*=i

if __name__ == '__main__':
    l = []
    print(os.cpu_count())
    start = time.time()
    for i in range(4):
        p = Process(target = work)
        # p = Thread(target = work)
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print(f'{stop-start}')

IO密集型

单核情况下,优先使用多线程

多核情况下,优先使用多线程

总结:IO密集型使用多线程

from multiprocessing import Process
from threading import  Thread
import os,time

def work():
    time.sleep(2)
    print('>>>>>>>>>')

if __name__ == '__main__':
    l = []
    print(os.cpu_count())
    start = time.time()
    for i in range(40):
        # p = Process(target = work)
        p = Thread(target = work)
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print(f'{stop-start}')

在高效执行多个IO密集型的程序:使用多进程+多线程

死锁

死锁现象:两个或两个以上的进程或线程在执行过程中因争夺资源而造成一种互相等待的现象,称为系统处于死锁状态,或者产生了死锁。

import time
from threading import Lock,Thread

mutex1 = Lock()
mutex2 = Lock()

def task():
    work1()
    work2()

def work1():
    mutex1.acquire()
    print('拿到锁1')
    mutex2.acquire()
    print('拿到锁2')
    mutex2.release()
    print('解开锁1')
    mutex1.release()
    print('解开锁2')

def work2():
    mutex2.acquire()
    time.sleep(1)
    mutex1.acquire()
    print('拿到锁2')
    mutex1.release()
    print('解开锁1')
    mutex2.release()
    print('解开锁2')

for i in range(10):
    t = Thread(target=task)
    t.start()

递归锁(RLock)

内部维护者一个Lock和counter变量,counter记录acquire的次数,release可以使counter次数减1,只有counter为0时,才能被使用

用于解决死锁问题,相当于连环锁,要么不用,要么一起拿过去

import time
from threading import RLock,Thread

mutex1 = mutex2= RLock()

def task():
    work1()
    work2()

def work1():
    mutex1.acquire()
    print('拿到锁1')
    mutex2.acquire()
    print('拿到锁2')
    mutex2.release()
    print('解开锁1')
    mutex1.release()
    print('解开锁2')

def work2():
    mutex2.acquire()
    time.sleep(1)
    mutex1.acquire()
    print('拿到锁2')
    mutex1.release()
    print('解开锁1')
    mutex2.release()
    print('解开锁2')

for i in range(10):
    t = Thread(target=task)
    t.start()

信号量(semaphore)

信号量:内置计数器,每当调用acquire内置计数器-1,调用release内置计数器+1,计数器不能小于0,计数器为0时,acquire会阻塞线程直到其他线程调用release

相当于锁店

import time
from threading import Lock,Thread,Semaphore

sm = Semaphore(10)

def task():
    work1()
    work2()

def work1():
    sm.acquire()
    print('拿到锁1')
    sm.acquire()
    print('拿到锁2')
    sm.release()
    print('解开锁1')
    sm.release()
    print('解开锁2')

def work2():
    sm.acquire()
    time.sleep(1)
    sm.acquire()
    print('拿到锁2')
    sm.release()
    print('解开锁1')
    sm.release()
    print('解开锁2')

for i in range(10):
    t = Thread(target=task)
    t.start()

线程队列

FIFO队列(Queue())

先进先出

import queue

q=queue.Queue()
q.put('first')
q.put('second')
q.put('third')

print(q.get())
print(q.get())
print(q.get())
'''
结果(先进先出):
first
second
third
'''

LIFO队列(lifoQueue())

后进后出

import queue

q=queue.LifoQueue()
q.put('first')
q.put('second')
q.put('third')

print(q.get())
print(q.get())
print(q.get())
'''
结果(后进先出):
third
second
first
'''

优先级队列(PriorityQueue())

  1. 首先根据第一个参数判断ascii表的数值大小

  2. 判断第二个参数中的汉字顺序

  3. 再判断第二参数中数字--> 字符串数字 ---> 中文

  4. 以此类推

import queue

q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((20,'a'))
q.put((10,'b'))
q.put((30,'c'))

print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''

(day30)GIL + 线程相关知识点的更多相关文章

  1. [OS] 线程相关知识点

    操作系统中引入进程的目的,是为了描述和实现多个程序的并发执行,以改善资源利用率以及提高系统吞吐量.那为什么还需要引入线程呢?下面我们先来回顾一下什么是进程: 进程有两个基本属性:·资源的拥有者:给每个 ...

  2. IOS开发涉及有点概念&相关知识点

    前言,IOS是基于UNIX的,用C/C+/OC直通系统底层,不想android有个jvm. 首先还是系统架构的分层架构 1.核心操作系统层 Core OS,就是内存管理.文件系统.电源管理等 2.核心 ...

  3. 进程 & 线程相关知识

    不管Java,C++都有进程.线程相关的内容.在这里统一整理吧. Python的线程,其实是伪线程,不能真正的并发.下面也有讲. 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序 ...

  4. 浅谈C#中的 async await 以及对线程相关知识的复习

    C#5.0以后新增了一个语法糖,那就是异步方法async await,之前对线程,进程方面的知识有过较为深入的学习,大概知道这个概念,我的项目中实际用到C#异步编程的场景比较少,就算要用到一般也感觉T ...

  5. 【Java基础】String 相关知识点总结

    String 相关知识点总结 字符串的不可变性 概述 String 被声明为 final,因此它不可继承 在 Java8 中,String 内部使用 char 数组存储数据 public final ...

  6. UITableView相关知识点

    //*****UITableView相关知识点*****// 1 #import "ViewController.h" // step1 要实现UITableViewDataSou ...

  7. Android开发涉及有点概念&相关知识点(待写)

    前言,承接之前的 IOS开发涉及有点概念&相关知识点,这次归纳的是Android开发相关,好废话不说了.. 先声明下,Android开发涉及概念比IOS杂很多,可能有很多都题不到的.. 首先由 ...

  8. iOS开发Swift篇(02) NSThread线程相关简单说明

    iOS开发Swift篇(02) NSThread线程相关简单说明 一 说明 1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明. 2)该文仅仅简单讲解NSThread在s ...

  9. IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) + xib相关知识点总结

    添加商品和商品名小项目(使用xib文件终结版) 小贴士:博文末尾有项目源码在百度云备份的下载链接. xib相关知识点总结 01-基本使用 一开始使用xib的时候,如果要使用自定义view的代码,就需要 ...

随机推荐

  1. java算法基础范例

    题目1:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?  1.程序分析: 兔子的规律为数列1,1,2,3 ...

  2. 常用HBase操作

    HBase是一个分布式.面向列的数据库,可以用来存储非结构化和半结构化的松散数据,具有高可靠.高性能.面向列.可伸缩的特性.通过行键(RowKey).列族(ColumnFamily).列(Column ...

  3. 看完您如果还不明白 Kerberos 原理,算我输!

    系统环境 操作系统:CentOS 6 或 CentOS 7 JDK 版本:1.8.0_151 Ambari 版本:2.6.1 HDP 版本:2.6.4.0 扩展链接 Kerberos原理--经典对话 ...

  4. Knative 实战:基于 Knative Serverless 技术实现天气服务-上篇

    提到天气预报服务,我们第一反应是很简单的一个服务啊,目前网上有大把的天气预报 API 可以直接使用,有必要去使用 Knative 搞一套吗?杀鸡用牛刀?先不要着急,我们先看一下实际的几个场景需求: 场 ...

  5. asp.netcore 3.0 Docker Nginx(震惊,原来docker是这样的!)

    引言 Docker发布于2013年,Docker是dotCloud公司创始人在法国期间发起的一个公司内部项目,他是dotCloud多年云技术的一个革新.Docker在容器基础上进行了一步的封装,从网络 ...

  6. windows安装Mycat并测试

    1.下载系统安装包 选择相应的版本进行下载,地址:http://dl.mycat.io/ .Mycat数据库分库分表中间件介绍 http://www.mycat.io/ 2.安装 安装mycat前需要 ...

  7. 基于hap的文件上传和下载

    序言 现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合hap利用spirng mvc实现文件的上传和下载,包括上传下载图片.上传下载文档.前端所使用的技术不限,本文 ...

  8. CNN之yolo目标检测算法笔记

    本文并不是详细介绍yolo工作原理以及改进发展的文章,只用做作者本人回想与提纲. 1.yolo是什么 输入一张图片,输出图片中检测到的目标和位置(目标的边框) yolo名字含义:you only lo ...

  9. 夯实Java基础系列11:深入理解Java中的回调机制

    目录 模块间的调用 多线程中的"回调" Java回调机制实战 实例一 : 同步调用 实例二:由浅入深 实例三:Tom做题 参考文章 微信公众号 Java技术江湖 个人公众号:黄小斜 ...

  10. phaser学习总结之Tween详解

    前言 在上一章phaser学习总结之phaser入门教程中,我们已经初步入门了phaser,并通过一个案例了解了phaser,现在我们需要对phaser中的对象进行讲解,本章需要讲解的是tween,即 ...