线程条件,模块threading
启动方式
for i in range(2):
t = threading.Thread(target=fib, args=(35,),kwargs=None,daemon=None,name=None)
t.start() #开始运行
#参数介绍
target:目标函数名称
args: 传递元组参数
kwargs:传递关键字参数
daemon:是否为守护进程 默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
name:是指的进程名称
#线程对象方法
t.start() #开始运行
t.join() 默认:子进程和父进程是异步执行的。所以保证子进程执行完需要加
t.isAlive() 返回true/false, 线程是否存活
t.isDaemon() 返回true/false, 线程是否为守护进程
线程变量
线程共享全局变量,用global修改即可
import threading
share_var = 3
def share(var):
global share_var
share_var = var + 1
print('--------var', share_var, id(share_var))
return share_var
if __name__ == '__main__':
thread_list = []
m = Manager()
share_dict = m.dict()
for i in range(2):
m = threading.Thread(target=share, args=(share_var,)) #1
thread_list.append(m)
m.start()
for i in thread_list:
i.join()
#Thread
# --------var 4 140726610685792
# --------var 5 140726610685824
# ------------end 5
常用方法
threading.current_thread()
返回当前线程对象
threading.enumerate()
返回当前存在的所有线程对象的列表
threading.get_ident()
返回线程pid
threading.main_thread()
返回主线程对象,类似 threading.current_thread();只不过一个是返回当前线程对象,一个是返回主线程对象
@profile
def hasthread():
for i in range(2):
t = threading.Thread(target=fib, args=(35,))
t.start()
main_thread = threading.current_thread() #返回当前Thread对象,对应于调用者的控制线程.
print(main_thread)
print('---------', threading.enumerate()) #返回当前活动的所有Thread对象的列表。这个列表包括守护线程,由守护线程创建的虚拟线程对象
for t in threading.enumerate():
if t is main_thread:
continue
t.join()
#用于线程同步机制的方法
threading.Lock()
from threading import Lock
lock = Lock()
class Account:
def __init__(self, balance):
self.balance = balance
def draw(account, amount):
with lock:
time.sleep(0.1)
if account.balance >= amount:
print(threading.current_thread().name,"取钱成功")
account.balance -= amount
print(threading.current_thread().name,"余额", account.balance)
else:
print(threading.current_thread().name, "取钱失败,余额不足")
if __name__ == '__main__':
account = Account(1000)
ta = threading.Thread(name="ta", target=draw,args=(account, 800))
tb = threading.Thread(name="tb", target=draw,args=(account, 800))
ta.start()
tb.start()
#线程互斥锁
threading.Rlock()
#线程可重入锁. 互斥锁acquire后无release,下次acquire则一直阻塞。重入锁可以多次acquire,引用计数-1.
threading.Condition()
import threading
import time
product = 19
# 一个线程等待特定条件,而另一个线程发出特定条件满足的信号。最好说明的例子就是「生产者 / 消费者」模型:
def consumer(cond):
global product
t = threading.current_thread()
with cond:
cond.wait() #等待被唤醒
if product > 0:
product -= 1
print(f"{t.name}: resource ready")
else:
print("resource exhausted")
def producer(cond):
global product
t = threading.current_thread()
with cond:
print(f"{t.name}: Making resource available")
product += 1
cond.notifyAll() # 释放waiter锁,唤醒消费者
condition = threading.Condition()
c1 = threading.Thread(name="c1", target=consumer, args=(condition,))
c2 = threading.Thread(name="c2", target=consumer, args=(condition,))
p1 = threading.Thread(name="p1", target=producer, args=(condition,))
p2 = threading.Thread(name="p2", target=producer, args=(condition,))
c1.start()
time.sleep(1)
c2.start()
time.sleep(1)
p1.start()
p2.start()
线程条件锁,和上面一样提供了acquire, release方法。
threading.Semaphore()
线程信号量:对共同资源访问的对象数量。互斥锁等同时间段只允许一个对象访问,信号量这里可以指定对象数量。
import time
import threading
from random import random
from threading import Thread,Semaphore
def foo(tid, sema):
with sema:
wt = random() * 2
time.sleep(wt)
print(f"{tid} release sema")
def foo1(tid):
wt = random() * 2
time.sleep(wt)
print(f"{tid} release sema")
if __name__ == '__main__':
tic = time.time()
sema = Semaphore(10) #信号量指的是对共同资源访问的对象数量
threads = []
for i in range(100):
t = Thread(target=foo, args=(i,sema))
threads.append(t)
t.start()
for t in threads:
t.join()
toc = time.time()
print(f"10个结束时间:{toc-tic}")
threading.Event()
使用场景:python线程的事件用于主线程控制其他线程的执行
事件其实就相当于一个全局变量(设置为True,未设置为False),线程通过这个全局变量的状态来控制自身
enent可以通过设置、等待、清除一个标识(flag),来进行线程间的控制
event只要set,clear,wait三个方法
使用前先实例化event = threading.Event()
event.wait()#线程阻塞,等待标志位被设置.flag=False,程序执行event.wait会阻塞。为True不阻塞
event.wait(second) 不写second就一直等待
event.set()#设置标志位为True
event.clear()#清除标志位,设置为False
enent.isSet()#标志位是否被设置
import time
import threading
from random import randint
TIMEOUT = 2
def consumer(event, l):
t = threading.currentThread()
while 1:
event_is_set = event.wait(TIMEOUT)
if event_is_set:
try:
integer = l.pop()
print('{} popped from list by {}'.format(integer, t.name))
event.clear() # 重置事件状态
except IndexError: # 为了让刚启动时容错
pass
def producer(event, l):
t = threading.currentThread()
while 1:
integer = randint(10, 100)
l.append(integer)
print('{} appended to list by {}'.format(integer, t.name))
event.set() # 设置事件
time.sleep(1)
event = threading.Event()
l = []
threads = []
for name in ('consumer1', 'consumer2'):
t = threading.Thread(name=name, target=consumer, args=(event, l))
t.start()
threads.append(t)
p = threading.Thread(name='producer1', target=producer, args=(event, l))
p.start()
threads.append(p)
for t in threads:
t.join()
参考连接:
lr:
1)https://blog.csdn.net/jgw2008/article/details/84759696