Python中的多任务(21)

本文介绍了Python中的多任务处理,包括同步和异步的概念,重点讲解了互斥锁在多线程同步中的作用及其优缺点。还探讨了死锁问题、生产者和消费者模式,并引入了队列、优先级队列和后入先出队列。此外,文章提到了全局解释器锁(GIL)对Python线程的影响以及协程作为轻量级线程在并发执行中的应用。
摘要由CSDN通过智能技术生成

同步异步

同步:协调同步,按预定的先后次序进行运行。
异步:

互斥锁

线程同步能够保证多个线程安全的访问竞争资源(全局内容),最简单的同步机制就是使用互斥锁。
threading模块中定义了Lock类

from threading import Thread,Lock#创建锁

g=0
def hanshu1():
    global g
    for i in range(100000):
        l.acquire()#锁定,默认为True
        g+=1
        l.release()#释放锁
    print("函数1",g)
def hanshu2():
    global  g
    for i in range(100000):
        l.acquire()
        g += 1
        l.release()
    print("函数2",g)
if __name__ == '__main__':
    l=Lock()
    t1=Thread(target=hanshu1)
    t2=Thread(target=hanshu2)
    t1.start()
    t2.start()
#第一个结束的肯定是大于100000
#第二个结束的时候才是200000
#思考模式:扔钢镚
'''
函数1 177131
函数2 200000
'''
from threading import Thread,Lock

g=0
def hanshu1():
    global g
    l.acquire()
    for i in range(100000):
        g+=1
    print("函数1",g)
    l.release()
def hanshu2():
    global  g
    l.acquire()
    for i in range(100000):
        g += 1
    print("函数2",g)
    l.release()
if __name__ == '__main__':
    l=Lock()
    t1=Thread(target=hanshu1)
    t2=Thread(target=hanshu2)
    t1.start()
    t2.start()
#这两个就会是第一个100000
#一个200000,因为第一个加完,第二个才回去加
'''
函数1 100000
函数2 200000
'''

总结:

锁的好处:
1.确保了某段关键代码只能由一个线程从头到尾完整地执行。
锁的坏处:
2.阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。
3.由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁。

死锁

from threading import Thread,Lock#创建锁
import time
g=0
def hanshu1():
    global g
    for i in range(100000):
        lock1.acquire()#锁定lock1锁定,lock2也锁定,lock1等lock2释放,lock2等lock1释放
        print('函数1锁1得到锁,请求锁2')
        time.sleep(1)
        lock2.acquire()
        print('111111111111111')
        g+=1
        lock2.release()
        lock1.release()#释放锁
    print("函数1",g)
def hanshu2():
    global  g
    for i in range(100000):
        lock2.acquire()  # 锁定
        print('函数2锁2得到锁,请求锁1')
        time.sleep(1)
        lock1.acquire()
        print('2222222222222')
        g += 1
        lock1.release()
        lock2.release()  # 释放锁
    print("函数2",g)
if __name__ == '__main__':
    lock1=Lock()
    lock2 = Lock()
    t1=Thread(target=hanshu1)
    t2=Thread(target=hanshu2)
    t1.start()
    t2.start()
    '''
函数11得到锁,请求锁2
函数22得到锁,请求锁1
'''

生产者和消费者

队列

常用操作

import queue
q=queue.Queue(3)
q.put(1)
q.put(2)
q.put(3)
print('11111111',q.full())
# q.put(4)
while q.qsize()>0:
    print(q.get())
# while q.qsize():
#     print(q.get())
print("结束")

for i in range(q.qsize()):
    print(q.get(),i)

队列优先级

#队列优先级:数字越小,优先级越高
import  queue
q=queue.PriorityQueue(5)
q.put((1,'香蕉'))
q.put((5,'葡萄'))
q.put((2,'西瓜'))
q.put((-9,'芒果'))
while q.qsize()>0:
    print(q.get())

'''
(-9, '芒果')
(1, '香蕉')
(2, '西瓜')
(5, '葡萄')
'''

后入先出队列

import  queue
q=queue.LifoQueue(4)#后入先出
q.put(1)
q.put(2)
q.put(5)
q.put(4)
while q.qsize()>0:
    print(q.get())
'''
4
5
2
1
'''

生产者与消费者模式

#生产者与消费者
from threading import Thread
import queue,time
def produce(q,name):
    count=1
    while True:
        bz=name+"生产的包子%d"%count
        q.put(bz)
        print(bz)
        time.sleep(1)
        count+=1
def consum(q,name):
    while True:
        bz=q.get()
        print(name,'吃',bz)
if __name__ == '__main__':
    q=queue.Queue(5)
    t1=Thread(target=produce,args=(q,"张三"))
    t2 = Thread(target=consum, args=(q, "李四"))
    t1.start()
    t2.start()
#生产者与消费者:两个人包包子,三个人吃
from threading import Thread
import queue,time
def produce(q,name):
    count=1
    while True:
        bz=name+"生产的包子%d"%count
        q.put(bz)
        print(bz)
        time.sleep(1)
        count+=1
def consum(q,name):
    while True:
        bz=q.get()
        print(name,'吃',bz)
if __name__ == '__main__':
    q=queue.Queue(5)
    p1=Thread(target=produce,args=(q,"张三"))
    p2 = Thread(target=produce, args=(q, "李四"))
    c1 = Thread(target=consum, args=(q, "小孩1"))
    c2 = Thread(target=consum, args=(q, "小孩2"))
    c3 = Thread(target=consum, args=(q, "小孩3"))
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    c3.start()

全局ThreadLocal对象

每个线程都只读自己线程的独立副本,互不干扰。

#当不是全局ThreadLocal对象时:
from threading import Thread
import time,threading
class A():
    pass
def hanshu1(name):
    A.name=name
    for i in range(1,1000000):
        pass
    hanshu2()
def hanshu2():
    # time.sleep(1)
    print(threading.current_thread(),A.name)
if __name__ == '__main__':
    t1=Thread(target=hanshu1,args=("张三",),name="线程帅哥")#name="线程帅哥"这是线程的名字
    t2 = Thread(target=hanshu1, args=("李四",), name="线程美女")
    t1.start()
    t2.start()
'''
<Thread(线程帅哥, started 4124)> 李四
<Thread(线程美女, started 12092)> 李四
'''
#改成ThreadLocal对象:
from threading import Thread
import time,threading
local=threading.local()

def hanshu1(name):
    local.name=name
    for i in range(1,1000):
        pass
    hanshu2()
def hanshu2():
    # time.sleep(1)
    print(threading.current_thread(),local.name)
if __name__ == '__main__':
    t1=Thread(target=hanshu1,args=("张三",),name="线程帅哥")#name="线程帅哥"这是线程的名字
    t2 = Thread(target=hanshu1, args=("李四",), name="线程美女")
    t1.start()
    t2.start()
'''
<Thread(线程帅哥, started 11892)> 张三
<Thread(线程美女, started 9424)> 李四
'''

全局解释器锁

对python虚拟机的访问是由全局解释器(GIL)控制的。这个锁是用来保证同时只能有一个线程运行的。
两个时间差不多。说明一次只能执行一个线程。

import time,threading
def hanshu2():
    s=time.time()
    count=0
    for i in range(100000000):
        count+=1
    e=time.time()
    print(e-s)
if __name__ == '__main__':
    t1=threading.Thread(target=hanshu2)
    t2 = threading.Thread(target=hanshu2)
    t1.start()
    t2.start()
'''
13.303761005401611
13.367764472961426
'''    
import time, threading


def hanshu1():
    s = time.time()
    count = 0
    for i in range(200000000):
        count += 1
    e = time.time()
    print(e - s)


if __name__ == '__main__':
    t1 = threading.Thread(target=hanshu1)
    t1.start()
'''
13.543774604797363
'''

协程

协程又称微线程。
协程是比线程更小的执行单元。为什么说他是一个执行单元,因为它自带Cpu上下文。
通俗的理解:在一个线程中的某个函数,都可以任何地方保存当前函数的所有变量等信息,来回切换由开发者决定。
生成器的状态也是可以保留的。

def hanshu():
    a=3
    for x in range(10):
        yield  x+a
        a+=1
x=hanshu()
for y in x:
    print(y)

'''
状态被保留
0+3
1+4
2+5

'''
def hanshu():
    for i in range(3):
        print("函数1",i)
        yield
def hanshu2(a):
    for i in range(3):
        next(a)
        print("函数2", i)
h=hanshu()
hanshu2(h)
'''
函数1 0
函数2 0
函数1 1
函数2 1
函数1 2
函数2 2
'''
def hanshu():
    for i in range(3):
        print("函数1",i)
        yield
def hanshu2(a):
    for i in range(3):
        next(a)
        print("函数2", i)
h=hanshu()
hanshu2(h)
'''
函数1 0
函数2 0
函数1 1
函数2 1
函数1 2
函数2 2
'''
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像的目标属于哪个类别。 定位问题:确定目标在图像的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值