Python多线程学习(中)
Posted sniper-huohuohuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python多线程学习(中)相关的知识,希望对你有一定的参考价值。
今天接着写多线程,最近几天一直在看多线程,但是书上的例子太难看了(可能我天生愚笨吧~_~),看了好久才搞懂,我看了两本书才搞明白书上的例子,所以大家在看书学习看不懂的时候,推荐多看几本一样知识点的书,在网上多看教程,辅助学习。
下面开始介绍锁和条件变量。
一。“锁”
锁是指在运行程序时,对于需要访问共享资源的多线程程序,为防止I/O密集型操作造成结果发生错误。
使用锁的方法: import threading
引入锁 lock = threading.Lock()
添加锁 lock.acquire()
对临界资源进行访问的代码
释放锁 lock.release()
假设对数字进行迭代输出,在不加锁的情况下,会导致输出全为15,加锁后是1,2,3,4.。。。。。13,14,15,最后输出‘all done‘
对于添加锁,添加锁后就只能一个线程对公共资源进行访问,所以在执行时速度会变慢,因为执行时等同于同步运行。
示例一代码:
#!/usr/bin/env python3.6 # -*- coding: utf-8 -*- #导入模 import threading import time from atexit import register import random lock = threading.Lock() a = 0 def print_sum(): global a lock.acquire() a += 1 time.sleep(1) print(str(a)) lock.release() def main(): th_list = [] for x in range(15): t = threading.Thread(target=print_sum,args=()) th_list.append(t) for x in th_list: x.start() @register def exit(): print(‘all done‘) if __name__ == ‘__main__‘: main()
二。条件变量
对于条件变量,可以添加一个判断条件,如果符合条件就执行,否则等待。
导入模块 from threading import Condition
该模块有acquirre()和release(),在不符合条件时,调用.wait(),此时线程就会挂起,调用.notify() 或.notify_all()来激活线程,再进行条件判断。
以消费--生产问题来进行对条件变量讨论。创建一个产品类,一个消费者类,一个生产者类,消费者有五个线程,生产者有一个线程,生产者不断生产,消费者持续消费,不会存在无限生产消费不完的问题,但是停止程序需要手动完成。
代码:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import threading import time import random #条件变量,消费者和生产者 #产品类 class Chan_pin(): def __init__(self): self.count = 0 #消费产品 def xiao_fei(self): self.count -= 1 #生产产品 def sheng_chan(self): self.count += 1 #判断产品是否为空 def pan_duan(self): return not self.count pass #生产类 class Sheng_chans(threading.Thread): def __init__(self,tiao_jian,chan_pin): super().__init__() self.tiao_jian = tiao_jian self.chan_pin = chan_pin def run(self): while True: self.tiao_jian.acquire() self.chan_pin.sheng_chan() print(‘已生产的产品数:%s‘ % self.chan_pin.count) self.tiao_jian.notify_all() self.tiao_jian.release() time.sleep(random.random()) pass #创建消费类 class Xiao_fei(threading.Thread): def __init__(self,chan_pin,tiao_jian): super().__init__() self.tiao_jian = tiao_jian self.chan_pin = chan_pin #重构run函数 def run(self): while True: self.tiao_jian.acquire() time.sleep(random.randint(2,5)) if self.chan_pin.pan_duan(): self.tiao_jian.wait() print(‘%s产品没了,请等待。。。‘ % threading.current_thread().name) else: self.chan_pin.xiao_fei() print(‘%s已消费,现剩余产品:%s‘ % (threading.current_thread().name,self.chan_pin.count)) self.tiao_jian.notify_all() self.tiao_jian.release() pass #创建实例。 def main(): tiao_jian = threading.Condition() chan_pin = Chan_pin() t1 = Sheng_chans(tiao_jian,chan_pin) t1.start() time.sleep(5) #t1.join() for x in range(5): t2 = Xiao_fei(chan_pin,tiao_jian) t2.start() print(threading.active_count()) print(threading.enumerate()) print(threading.enumerate()[-2].is_alive()) #t2.join() #运行 if __name__ == ‘__main__‘: main()
三。信号量
信号量允许添加指定个数的线程对公共资源进行访问。
对于信号量有两个模块可用,分别是:Semaphore和BoundedSemaphore 前一个模块比第二个有一个缺点,第一个在进行调用.release()时,添加数超过设定数时不会报错,而第二个会进行报错。
本文章主要对第二个进行介绍。
该模块有两个方法, .acquire()和.release() 在调用.acquire()时会减一,当减到0时,会停止线程运行,进入等待;调用.release()时会加一。
调用方法:
num = 5 #表示只允许5个线程对公共资源进行访问。
a = BoundedSemaphore(num)
a.acquire()
要执行的代码
a.release()
下面是示例代码:
1 #!/usr/bin/env python3.6 2 # -*- coding: utf-8 -*- 3 #导入模 4 import threading 5 import time 6 from atexit import register 7 8 9 #要操作的公共资源,设置一个列表,多个线程对列表进行访问,输出列表内容。 10 11 num = 3 12 a = threading.BoundedSemaphore(num) 13 #创建一个输出内容的函数 14 def print_list(list): 15 a.acquire() 16 p = threading.current_thread().name 17 if a.acquire(False): 18 print(‘%s : 不能运行‘ % p) 19 else: 20 print(‘%s:%s‘ % (p,list)) 21 a.release() 22 23 #继承线程类 24 class New_thread(threading.Thread): 25 def __init__(self,han_name,han_can): 26 super().__init__() 27 self.han_name = han_name #函数名 28 self.han_can = han_can #要传入函数的参数 29 def run(self): 30 self.han_name(self.han_can) 31 pass 32 33 # 34 def main(): 35 list_1 = [‘aaaa‘, ‘bbbb‘, ‘cccc‘, ‘dddd‘, ‘eeee‘, ‘ffff‘] 36 #线程列表 37 thread_list = [] 38 #创建十个线程 39 for x in range(5): 40 t = New_thread(print_list,list_1) 41 thread_list.append(t) 42 for x in thread_list: 43 x.start() 44 #print(thread_list) 45 46 #创建回调函数。 47 @register 48 def exit(): 49 print(‘all done‘) 50 51 if __name__ == ‘__main__‘: 52 main()
以上就是关于多线程的锁,信号量,条件变量,有不对的地方还望多指教。
以上是关于Python多线程学习(中)的主要内容,如果未能解决你的问题,请参考以下文章