python3,线程,锁,队列相关实操备忘
#!/usr/bin/env python3
'''
threadin模块多线程锁的种类(通常用递归锁RLock替代普通锁Lock使用):
1.t=threading.Lock(): 单纯的锁,不过多个锁时,可能会造成死锁!
t.acquire() 启动锁:以下代码单线程一直执行,中间不切换到其它线程
t.release() 释放锁:让其它线程可操作
2.t.threading.RLock():
递归锁(解决死锁问题):一个锁可重复使用,互相嵌套,内附有锁的计数器。释放锁也是由内到外,只有最外层的锁释放后,其它线程才可使用。
释放一个锁,计数器减1
3. 信号量:也是锁的一种!以下设置可同时并发5个线程对锁内指令进行操作!某个线程先执行完,其它线程可再次进入执行!同样内含计数器
semaphore = threading.BoundedSemaphore(5)
4.条件变量同步:也是一种锁,可实现线程之前的沟通!..默认使用递归锁RLock.
lock_con = threading.Condition()
lock_con.acquire()--启动锁;lock_con.release()--释放锁;lock_con.wait()--释放锁并进入阻塞状况,等待notify激活后重新从acquire开始执行;
lock_con.notify()--通知在wait()状态的锁可以开始执行了。即激活作用!
5. 同步条件event:没有锁的功能,内含一标志位(True、False).实现不同线程之前的通讯控制
event.isSet():返回event的状态值;
event.set():设置event状态值为True!所有阻塞池的线程激活进入就绪状态;等待os调度;
event.wait():如果 event.isSet() == False,将阻塞线程
event.clear():恢复event的状态值为False
6.queue:队列,一个结构数据类型,多线程利器!默认FIFO(先进行出);自带锁!保证多线程操作时,队列里的唯一性及数据安全!
import queue
q = queue.Queue(10); 创建队列对象;参数10代表队列允许的数量为10个。0或是负数代表无穷大
q.put(item,block,timeout),把item数据放入队列中,block默认True,作用是队列满时,阻塞(不报错)!,如果设置为False,则队列满时,再放数据会报错;
timeout:设置阻塞超时;
q.get(block,timeout):默认先进先出原则取出数据
q.full()和q.empty():判断队列满或空。返回True或False
q.qsize():返回队列大小
'''
import threading
import time
from random import randint
import queue
class Producer(threading.Thread):
def run(self):
while True:
val = randint(0,100)
q.put(val)
print("面包师%s生产了%s号包子"%(self.name, str(val)))
time.sleep(2)
class Consumer(threading.Thread):
def run(self):
while True:
re = q.get()
print("客户%s吃掉了%s号包子"%(self.name,re))
time.sleep(0.5)
if __name__ == "__main__":
q = queue.Queue(10) #创建一个队列,队列允许的最大成员数是10个,多了造成阻塞,得有出去的,才能进来!
threads = [] # 放所有线程名称的列表
for t in range(5):
threads.append(Producer()) # 创建3个线程,对应3个生产者对象---Producer()通过类方式创建了一个线程
threads.append(Consumer())
for i in threads:
i.start()
for j in threads:
j.join()
'''
class boss(threading.Thread):
def run(self):
print("%s说今天晚上大家都加班到晚上24:00"%(self.name))
event.isSet() or event.set() # 在x or y的值只可能是x或y。 当x为true时是x, x为false时是y.即event状态只能是True
time.sleep(5)
print("%s:时间到了,大家可以下班了!!"%(self.name))
event.isSet() or event.set()
class worker(threading.Thread):
def run(self):
event.wait() # 阻塞线程
print("worker: ai......命苦啊。。。")
time.sleep(1)
event.clear()
event.wait()
print("worker: HAHAAHAHA")
if __name__ == "__main__":
event = threading.Event() # 启动线程控制状态
threads = []
for t in range(5):
threads.append(worker())
threads.append(boss())
for i in threads:
i.start()
for j in threads:
j.join()
'''
'''
class Account:
def __init__(self,id,balance):
self.id = id
self.balance = balance
def withdraw(self,num):
r.acquire()
self.balance -= num
r.release()
def deposit(self,num):
r.acquire()
self.balance += num
r.release()
def transfer(_from,_to,count):
_from.withdraw(count)
_to.deposit(count)
if __name__ == "__main__":
r = threading.RLock() # 递归锁(解决死锁问题):一个锁可重复使用,互相嵌套,内附有锁的计数器。
a1 = Account("zuly",1000)
a2 = Account("mary",2000)
t1 = threading.Thread(target = transfer, args = (a1,a2,300))
t2 = threading.Thread(target = transfer, args = (a2,a1,100))
t1.start()
t2.start()
print("%s 的 balance 是%s"%(a1.id,a1.balance))
print("%s 的 balance 是%s"%(a2.id,a2.balance))
'''
'''
#********信号量使用************
class MyThread(threading.Thread):
def run(self):
semaphore.acquire()
print("这是%s在执行代码"%(self.name))
time.sleep(2)
semaphore.release()
if __name__ == "__main__":
semaphore = threading.BoundedSemaphore(5) # 创建信号量,并设置最多同时只能有5个线程可对代码并发操作。同时启动线程计数器
threads = []
for t in range(20):
threads.append(MyThread())
for i in threads:
i.start()
for j in threads:
j.join()
print("this is end!")
'''
'''
#********条件锁使用************
# 通过自定义类方式创建了一个线程:自定义的类必须有父类threading.Thread,必须有run(self)。此方法内容为要执行的逻辑代码
class Producer(threading.Thread):
def run(self):
global L
while True:
val = randint(0,100)
if lock_con.acquire(): # 启动锁
print("面包师%s生产了一个%s的包子放在了%s中"%(self.name, str(val),L))
L.append(val)
lock_con.notify() # 知在wait()状态的锁可以开始执行了。即激活作用!
lock_con.release()
time.sleep(3)
class Consumer(threading.Thread):
def run(self):
global L
while True:
lock_con.acquire() # 启动锁
if len(L) == 0:
lock_con.wait() # 释放锁并进入阻塞状况,等待notify激活后重新从acquire开始执行;
print("客户%s吃掉了1个%s的包子"%(self.name,L[0]))
del L[0]
lock_con.release() # 释放锁
time.sleep(0.25)
if __name__ == "__main__":
L = [] # 放生产完的包子
lock_con = threading.Condition() #创建一个条件锁:方便不同线程之间沟通
threads = [] # 放所有线程名称的列表
for t in range(5):
threads.append(Producer()) # 创建5个线程,对应5个生产者对象---Producer()通过类方式创建了一个线程
threads.append(Consumer())
for i in threads:
i.start()
for j in threads:
j.join()
'''