Python 多线程中的 Join Lock 和 Event
Join 函数的作用
Join 函数的作用主要是提供当前线程阻塞,等待线程结束后,在执行下一个线程,保护线程通畅有序执行
如下当没有使用 join 时,主线程结束了子线程还在运行
def doWaiting1():
print('start waiting1: ' + time.strftime('%H:%M:%S') + "\n")
time.sleep(3)
print("线程1奉命报道")
print('stop waiting1: ' + time.strftime('%H:%M:%S') + "\n")
def doWaiting2():
print('start waiting2: ' + time.strftime('%H:%M:%S') + "\n")
time.sleep(8)
print("线程2奉命报道")
print('stop waiting2: ', time.strftime('%H:%M:%S') + "\n")
# 创建并开启线程1
thread1 = threading.Thread(target = doWaiting1)
thread1.start()
# thread1.join()
# 创建并开启线程2
thread2 = threading.Thread(target = doWaiting2)
thread2.start()
# thread2.join()
# 计时程序
print('start join: ' + time.strftime('%H:%M:%S') )
print('end join: ' + time.strftime('%H:%M:%S') )
start waiting1: 20:44:06
start waiting2: 20:44:06
start join: 20:44:06
end join: 20:44:06
线程1奉命报道
stop waiting1: 20:44:09
线程2奉命报道
stop waiting2: 20:44:14
Lock 的作用
在同一进程下的线程间资源是共享的,使用线程锁可以有效的保护共享资源。资源共享意味着所有线程均可以修改资源,而线程的执行是抢占式的,cpu执行任务的时候是不定规律执行的,同时会执行多个语句,多个线程在同一个进程中可以并发执行,当第一个线程读取数据时,第二个线程在修改数据,将会导致冲突。如果发生数据修改的操作,为防止数据资源冲突,可以给线程加锁,以保护资源。
线程锁原理:只有当被加锁的线程执行完毕,并释放锁,其他线程才可以对该线程所占用的资源进行操作使用
如下当不设进程锁时,会出现打印错乱,就是因为进程之间抢占资源造成的
lock = threading.Lock()
def add1():
global a
# lock.acquire()
for i in range(10000):
a = a+1
print(a)
# lock.release()
def add2():
global a
# lock.acquire()
for i in range(10000):
a = a+1
print(a)
# lock.release()
a = 1
t1 = threading.Thread(target=add1, )
t2 = threading.Thread(target=add1, )
t1.start()
t2.start()
Event 的使用
set() — 全局内置标志Flag,将标志Flag 设置为 True,通知在等待状态(wait)的线程恢复运行;
isSet() — 获取标志Flag当前状态,返回True 或者 False;
wait() — 一旦调用,线程将会处于阻塞状态,直到等待其他线程调用set()函数恢复运行;
clear() — 将标志设置为False;
Event 可以用来控制一个线程中不同子功能的开启,也可以用来实现两个线程之间的联动,即一个线程满足某种条件触发另外一个线程功能的启动
import threading
from time import sleep
event = threading.Event()
def test(n):
while not event.is_set():
print('event is not set')
sleep(1)
event.wait()
while event.is_set():
print('event is set')
sleep(1)
if __name__ == '__main__':
t = threading.Thread(target=test, args=(1, ))
t.start()
sleep(3)
print('----- event is set -----')
event.set()
sleep(3)
print('----- event is clear -----')
event.clear()
event is not set
event is not set
event is not set
----- event is set -----
event is set
event is set
event is set
----- event is clear -----
生产者与消费之--Event版
# -*- coding:utf-8 -*-
import threading
import time
import queue
event = threading.Event()
goods = queue.Queue(5)
num = 0
class Producer(threading.Thread):
def run(self):
global num
while True:
if goods.empty():
event.clear()
for _ in range(5):
goods.put('商品-' + str(num))
print('生产了商品-{0}.'.format(str(num)))
num += 1
time.sleep(1)
event.set()
class Customer(threading.Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.money = 7
def run(self):
while self.money:
event.wait()
self.money -= 1
print('{0} 买了一个{1}.'.format(
threading.current_thread().name, goods.get()))
time.sleep(1)
print('{0}没钱了,回家.'.format(threading.current_thread().name))
if __name__ == '__main__':
p = Producer(daemon=True)
c1 = Customer(name='Alice')
c2 = Customer(name='Bob')
c2.start()
p.start()
c1.start()
c1.join()
c2.join()