关于python的多线程的Condition问题,制作了一个实验
程序员文章站
2022-05-02 16:55:51
...
实验代码如下,可以直接运行。实验结论可能跟文档的解释不太一样。
import threading
import time
condi = threading.Condition()
N =1
condi2 = threading.Condition()
def tar01():
global N
with condi:
print('%s is started'%threading.current_thread().name)
print(N)
N +=1
time.sleep(0.1)
print('in %s,wait01 is triggered'%threading.current_thread().name)
condi.wait()
print('in %s,notify 01 is triggered'%threading.current_thread().name)
condi.notify()
print('in %s,notify 01 finished'%threading.current_thread().name)
def tar02():
global N
with condi:
print('%s is started'%threading.current_thread().name)
print(N)
N +=1
time.sleep(0.1)
print('in %s,notify 02 is triggered'%threading.current_thread().name)
condi.notify()
print('in %s,wait 02 is triggered'%threading.current_thread().name)
condi.wait()
print('in %s,wait 02 finished'%threading.current_thread().name)
def tar03():
global N
with condi:
print('%s is started'%threading.current_thread().name)
print(N)
N += 1
time.sleep(0.1)
print('in %s,notify 03 is triggered'%threading.current_thread().name)
condi.notify()
print('in %s,wait 03 is triggered'%threading.current_thread().name)
condi.wait()
print('in %s,wait 03 finished'%threading.current_thread().name)
# print('in %s,notify 03 is triggered'%threading.current_thread().name)
# condi.notify()
# print('in %s,notify 03 finished'%threading.current_thread().name)
def tar04():
with condi2:
print('%s is started'%threading.current_thread().name)
for i in range(1,7,2): #打印1到6之间的基数,因为起始点是1,步长是2
print(i)
time.sleep(0.1)
print('in %s,notify 01 is triggered'%threading.current_thread().name)
condi2.notify()
print('in %s,wait 01 is triggered'%threading.current_thread().name)
condi2.wait()
print('in %s,wait 01 finished'%threading.current_thread().name)
# print('in %s,notify 01 is triggered'%threading.current_thread().name)
# condi2.notify()
# print('in %s,notify 01 finished'%threading.current_thread().name)
def tar05():
with condi2:
print('%s is started'%threading.current_thread().name)
for i in range(2,7,2): #打印1到6之间的偶数,因为起始点是2,步长是2
print(i)
time.sleep(0.1)
print('in %s,notify 02 is triggered'%threading.current_thread().name)
condi2.notify()
print('in %s,wait 02 is triggered'%threading.current_thread().name)
condi2.wait()
print('in %s,wait 02 finished'%threading.current_thread().name)
key = input('press Enter to go mod A,else: press other key: ')
if key == '':
for i in range(2):
# 这个for循环的含义就是每轮开启3个线程,由于第1轮循环开启的时候,第1轮循环开启的线程尚未结束,
# 所以第2轮同时又开启了3个循环。并且,由于第二轮开启的时候,第一轮循环里的第一个受制于condition的函数尚未结束,
# 并且这6个线程在代码中还受制于同一个condition,所以他们在实际运行中也是受制于同一个condition的
# 所以,他们必然要依次开启一同结束。受到同一个condition制约的线程是同时结束的
threading.Thread(target=tar01).start()
threading.Thread(target=tar02).start()
threading.Thread(target=tar03).start()
else:
# t1 = threading.Thread(target= tar01) # 这三次个线程即使没有被使用,也被创建了出来,并占用了头两个线程的编号
# t2 = threading.Thread(target= tar02)
# t3 = threading.Thread(target= tar03)
threading.Thread(target=tar04).start()
threading.Thread(target=tar05).start()
# print('+++++++++++++++finished+++++++++++++++')
# 运行结果证明:
# 1. 在循环执行两次两个tar01和tar02时,tar02唤醒的原因是tar02.wait(),
# 2. notify()函数是用来告诉Condition,如果再没有新的线程需要等待的,那么本线程可以结束了的,
# 以及如果线程池里只剩下一个处于等待状态的线程时,这个线程也被**并运行这个线程剩余的代码
#下面是不同情况的具体总结:
# +++++++++++++++++++
# 对于顺序执行tar01 tar02 tart03的情况
if 1 == 1:
pass
# press Enter to go mod A,else: press other key:
# Thread-1 is started
# 1
# in Thread-1,wait01 is going to work
# Thread-2 is started
# 2
# in Thread-2,notify 02 is going to work
# in Thread-2,wait 02 is going to work
# Thread-3 is started
# 3
# in Thread-3,notify 03 is going to work
# in Thread-3,wait 03 is going to work
# Thread-4 is started
# 4
# in Thread-4,wait01 is going to work
# Thread-5 is started
# 5
# in Thread-5,notify 02 is going to work
# in Thread-5,wait 02 is going to work
# Thread-6 is started
# 6
# in Thread-6,notify 03 is going to work
# in Thread-6,wait 03 is going to work
# in Thread-1,notify 01 is going to work
# in Thread-1,notify 01 finished
# in Thread-5,wait 02 finished
# in Thread-2,wait 02 finished
# in Thread-3,wait 03 finished
# in Thread-4,notify 01 is going to work
# in Thread-4,notify 01 finished
# in Thread-6,wait 03 finished
#
# Process finished with exit code 0
# +++++++++++++++++++++++++++++++++++++++++
#对于tar04和tar05的情况:假如每个函数循环的总次数是偶数,
if 1 == 1:
pass
# 比如:
# tar04执行for循环的次数为3次,for i range(1,7,2) 循环打印的是1,3,5
# tar05执行for循环的次数为3次,for i range(2,7,2) 循环打印的是2,4,6
# 那么tar04写成先wait再notify,tar05写成先notify再wait的话,这样的两个线程是可以都结束的。
# 程序运行结果如下:
# press Enter to go mod A,else: press other key: p
# Thread-1 is started
# 1
# in Thread-1,wait 01 is triggered #这两部清晰的证明wait会导致下一个Condition函数被release
# Thread-2 is started
# 2
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# in Thread-1,notify 01 is triggered
# in Thread-1,notify 01 finished
# 3
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# 4
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# in Thread-1,notify 01 is triggered
# in Thread-1,notify 01 finished
# 5
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# 6
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# in Thread-1,notify 01 is triggered
# in Thread-1,notify 01 finished
# in Thread-2,wait 02 finished
# Process finished with exit code 0
# +++++++++++++++++++++++++++++++++++++++++
#如果把tar04和tar05都写成先nofity再wait的形式;
if 1 == 1:
pass
# 就会导致在执行最后一步循环时,tar04结束之后没有运行notify函数通知处于等待状态的tar05被唤醒,
# 从而一直hang在那里,运行结果如下:
# press Enter to go mod A,else: press other key: p
# Thread-1 is started
# 1
# in Thread-1,notify 01 is triggered
# in Thread-1,wait 01 is triggered
# Thread-2 is started
# 2
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# 3
# in Thread-1,notify 01 is triggered
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# 4
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# 5
# in Thread-1,notify 01 is triggered
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# 6
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is triggered
# in Thread-1,wait 01 finished
# +++++++++++++++++++++++++++++++++++++++++
#对于tar04和tar05的情况:假如两个Condition函数运行的总次数是奇数,比如:
if 1 == 1:
pass
# tar04执行for循环的次数为3次,for i range(1,6,2) 循环打印的是1,3,5
# tar05执行for循环的次数为2次,for i range(2,6,2) 循环打印的是2,4
# 那么tar04写成先wait再notify,tar05写成先notify再wait的话,线程2可以结束,但是线程1无法结束。
# 因为tar05少了一个wait来通知tar04继续运行notify
# 程序的运行结果如下:
# press Enter to go mod A,else: press other key: p
# Thread-1 is started
# 1
# in Thread-1,wait 01 is triggered
# Thread-2 is started
# 2
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is riggered
# in Thread-1,wait 01 finished
# in Thread-1,notify 04 is tgriggered
# in Thread-1,notify 04 finished
# 3
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# 4
# in Thread-2,notify 02 is triggered
# in Thread-2,wait 02 is riggered
# in Thread-1,wait 01 finished
# in Thread-1,notify 04 is tgriggered
# in Thread-1,notify 04 finished
# 5
# in Thread-1,wait 01 is triggered
# in Thread-2,wait 02 finished
# ++++++++++++++++++++++
# 无论两个Condition函数执行for循环的次数为奇数还是偶数,都不能写成先同时先notify再wait的形式。
if 1 == 1:
pass
# 假如把tar04和tar05都写成先nofity再wait的样子,两个线程依然会交替运行,
# 但是就会导致在最后一个循环时线程1已经由于notify而结束,但是没有wait来触发tar05继续执行tar05的nofity
# 所以 tar05会一直hang在那里
# 结果如下:
# press Enter to go mod A, else: press other key: p
# Thread - 1 is started
# 1
# in Thread - 1, notify 01 is triggered
# in Thread - 1, wait 01 is triggered
# Thread - 2 is started
# 2
# in Thread - 2, notify 02 is triggered
# in Thread - 2, wait 02 is riggered
# in Thread - 1, wait 01 finished
# 3
# in Thread - 1, notify 01 is triggered
# in Thread - 1, wait 01 is triggered
# in Thread - 2, wait 02 finished
# 4
# in Thread - 2, notify 02 is triggered
# in Thread - 2, wait 02 is riggered
# in Thread - 1, wait 01 finished
# 5
# in Thread - 1, notify 01 is triggered
# in Thread - 1, wait 01 is triggered
# in Thread - 2, wait 02 finished
# 6
# in Thread - 2, notify 02 is triggered
# in Thread - 2, wait 02 is riggered
# in Thread - 1, wait 01 finished
# +++++++++++++++++++
# 关于Condition
if 1 == 1:
pass
# 当你在程序的末尾启动# print('+++++++++++++++finished+++++++++++++++')时,会看到下面的情况。
# 也就是说,以Condition控制的多线程,不会导致程序在多线程执行完毕之前被阻塞,
# 所以,当你Condition多线程后面还有代码需要使用Condition多线程的结果时,你要特别留意这个问题。
# 结果如下
# Thread-1 is started
# 1
# +++++++++++++++finished+++++++++++++++
# 后面的结果省略
上一篇: (爬虫基础)爬取猫眼Top100电影
下一篇: 关于多线程中的死锁问题