python多线程与其生产消费

Python多线程详解
本文深入探讨了Python的threading模块,包括Thread、Lock、RLock等类的使用,以及join()、setDaemon()等方法的功能。解析了多线程在不同任务类型上的执行效率,并详细说明了全局解释器锁(GIL)的作用和必要性。

threading模块包含下面的类:

  • Thread:基本线程类
  • Lock:互斥锁
  • RLock:可重入锁,使单一进程再次获得已持有的锁(递归锁)
  • Condition:条件锁,使得一个线程等待另一个线程满足特定条件,比如改变状态或某个值。
  • Semaphore:信号锁。为线程间共享的有限资源提供一个”计数器”,如果没有可用资源则会被阻塞。
  • Event:事件锁,任意数量的线程等待某个事件的发生,在该事件发生后所有线程被激活
  • Timer:一种计时器
  • Barrier:Python3.2新增的“阻碍”类,必须达到指定数量的线程后才可以继续执行。

 

thread是低级模块,threading是高级模块,绝大多数情况下,我们只需要使用threading这个高级模块

 

方法:

join()方法:希望主线程等等子线程,不要“埋头往前跑”

setDaemon(True):把所有的子线程都变成主线程的守护线程,当主线程结束后,守护子线程也会随之结束,整个程序也跟着退出

Python针对不同类型的任务,多线程执行效率是不同的:

Python下的多线程对CPU密集型任务并不友好,对IO密集型任务比较友好。

 

全局解释器锁(GIL),为什么不能去掉GIL?

GIL:任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。

GIL的移除给单线程程序的执行速度带来了一定的负面影响

 

线程和进程都是CPU工作时段的描述

进程是爹妈,管着众多的线程儿子

进程:独立功能的程序,系统分配资源的一个独立单位,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响

线程:进程的一个实体,CPU调度的基本单位,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改

          因此:为了避免多线程数据的紊乱,提出了线程锁,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。

             eg:

lock = threading.Lock()
 lock.acquire()
lock.release()

 

 

协程: 协程的调度完全由用户控制,

 

多线程数据错乱案例:

import time, threading

# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
   # print('n',n)
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(1000000):
        change_it(n)

if __name__ == '__main__':

    t1 = threading.Thread(target=run_thread, args=(5,))
    t2 = threading.Thread(target=run_thread, args=(8,))
    t1.start()
    t2.start()
    print (balance)
    t1.join()
    t2.join()
    print (balance)

 

结果:

0
5

 

加锁后:

import time, threading
lock=threading.Lock()
# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
   # print('n',n)
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(1000000):
        lock.acquire()
        change_it(n)
        lock.release()

if __name__ == '__main__':

    t1 = threading.Thread(target=run_thread, args=(5,))
    t2 = threading.Thread(target=run_thread, args=(8,))
    t1.start()
    t2.start()
    print (balance)
    t1.join()
    t2.join()
    print (balance)

结果:

0
0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值