python 消息队列_Python基础-多线程(线程创建/线程同步/死锁问题/消息队列)(19)

多线程

概念

线程是进程中一个“单一的连续控制流程”/执行路径

  • 线程被称为轻量级进程
  • 一个进程可以拥有多个并行的线程
  • 一个进程中的线程共享相同的内存单元/内存地址空间(可以访问相同的变量和对象),而且他们从同一个堆中分配对象(通信,数据交换,同步操作)
  • 由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这使得通信更简便并且信息传递的速度更快。
线程几种状态

多线程程序的执行顺序是不确定的,当执行到sleep时,线程将被阻塞(bloceed),到sleep结束后,线程进入就绪(runable)状态等待调度。而线程调度将自行选择一个线程执行。

ff81bb204b5b11c3a90ff3f57bc24b88.png

在这里插入图片描述

多线程创建方式

py中的thread模块是比较底层的模块,而threading模块是对thread模块做了一些包装,使之可以更方便的被调用。

threading模块
  • threading.enumrate(): 查看当前进程线程数量
threading.Thread类
  • 初始化参数:和多进程Process的初始化方法作用一致
  • is_alive():是否存活
  • join(): 等待创建的线程执行完
  • run():线程创建后需要执行的方法,可以被重写
  • start():启动线程
创建线程方式一:传入方法运行
import os,time,random,threadingdef say(name):    print('%sSorry'%name)if __name__=='__main__':    t=threading.Thread(target=say,args=('MM',))    t.start()    t.join()'''MMSorry'''
创建线程方式二:子类化
import os,time,random,threadingclass Thread_Test(threading.Thread):    def __init__(self,name):        #注意:初始化要放在参数赋值前面        threading.Thread.__init__(self)        self.name=name    def run(self):        print('当前进程名%s'%(self.name,))if __name__=='__main__':    t=Thread_Test('MM')    t.start()    t.join()'''当前进程名MM'''
线程共享全局变量问题
  • 优点:在一个进程内的所有线程共享全局变量,能够在不适用其它方式的前提下完成多线程之间的数据共享
  • 缺点:线程对全局变量的随意改变可能造成多线程对全局变量的混乱。
共享全局变量编程:使用global关键字

当然也可以使用给方法传参的方式

import os,time,random,threadingnum=100def fun1():    #声明num为全局变量    global num    for i in range(3):        num+=1        print(str(num),'>>>fun1')def fun2():    global num    print(num,'>>>fun2')t1=threading.Thread(target=fun1)t1.start()time.sleep(1)t2=threading.Thread(target=fun2)t2.start()'''通过结果可以看出,两个线程共享num变量101 >>>fun1102 >>>fun1103 >>>fun1103 >>>fun2'''
ThreadLocal变量
  • 一个ThreadLocal变量虽然是全局变量,但是每个线程都只能读写自己线程的独立副本。这样就解决了参数在一个线程中各个参数之间的传递问题。
  • ThreadLocal最常用的操作就是为每一个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用函数都可以方便的访问资源。
import os,time,random,threadingdef fun1(name):    local.name=name    fun2()def fun2():    name=local.name    print(name)#创建全局的ThreadLocal对象local=threading.local()for i in range(5):    threading.Thread(target=fun1,args=(i,)).start()
线程同步问题(加锁)
概念
  • 多个线程几乎在同时修改某一共享数据时,需要进行同步控制
  • 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制就是引入互斥锁
  • 互斥锁保证每次只有一个线程能够进程写操作,从而保证数据的准确性
  • threading模块定义了lock类来进行锁操作
lock类
  • Lock():创建锁
  • acquire([blocking]): 进入同步状态,如果blocking为True,则当前线程会阻塞,直到获取锁,False则不会阻塞。默认为True。
  • release():释放锁
同步编程
import os,time,random,threadingnum=100def fun1():    #声明num为全局变量    global num    #获取锁    lock.acquire()    try:        for i in range(100):            num += 1            print(str(num), '>>>fun1')    finally:        #释放锁        lock.release()def fun2():    global num    lock.acquire()    try:        for i in range(100):            num += 1            print(str(num), '>>>fun2')    finally:        lock.release()lock=threading.Lock()t1=threading.Thread(target=fun1)t1.start()time.sleep(1)t2=threading.Thread(target=fun2)t2.start()
死锁问题

线程间共享多个资源时,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会进入死锁状态。

import os,time,random,threadingnum=100def fun1():    #声明num为全局变量    global num    #获取锁    lock1.acquire()    try:        print('>>>fun1')        time.sleep(1)        lock2.acquire()        for i in range(100):            num += 1            print(str(num), '>>>fun1')        lock2.release()    finally:        #释放锁        lock1.release()def fun2():    global num    lock2.acquire()    print('>>>fun2')    time.sleep(1)    try:        lock1.acquire()        for i in range(100):            num += 1            print(str(num), '>>>fun2')        lock1.release()    finally:        lock2.release()lock1=threading.Lock()lock2=threading.Lock()t1=threading.Thread(target=fun1)t2=threading.Thread(target=fun2)t1.start()t2.start()'''>>>fun1>>>fun2'''

线程间消息队列

py的Queue模块提供了同步的,线程安全的队列类

  • FIFO(先进先出):Queue
  • LIFO(先进后出): LifoQueue ,栈模式
  • 优先级队列:PriorityQueue

这些队列都是实现了锁原语(原子操作),可以在多线程中直接使用。

生产者消费者
from queue import Queue,LifoQueue,PriorityQueueimport os,time,random,threadingclass Producer(threading.Thread):    global queue    def run(self):        count=0        while True:            if queue.qsize()<1000:                count+=1                msg='生产者'+str(count)                queue.put(msg)                print(msg)class Consumer(threading.Thread):    def run(self):        global queue        while True:            if queue.qsize()>0:                msg=self.name+'消费了'+queue.get()                print(msg)#queue=Queue()queue=PriorityQueue()#queue=LifoQueue()for i in range(5):    Producer().start()for i in range(5):    Consumer().start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值