我目前正在学习使用Python中的线程,我正在使用以下虚拟代码进行练习:
import threading
import queue
import time
my_queue = queue.Queue()
lock = threading.Lock()
for i in range(5):
my_queue.put(i)
def something_useful(CPU_number):
while not my_queue.empty():
lock.acquire()
print("\n CPU_C " + str(CPU_number) + ": " + str(my_queue.get()))
lock.release()
print("\n CPU_C " + str(CPU_number) + ": the next line is the return")
return
number_of_threads = 8
practice_threads = []
for i in range(number_of_threads):
thread = threading.Thread(target=something_useful, args=(i, ))
practice_threads.append(thread)
thread.start()
所有这些只需要创建一个包含5个项目的队列,然后将它们拉出并用不同的线程打印出来。你知道吗
不过,我注意到一些线程没有正确终止。例如,如果我后来在队列中添加了一些内容(例如my_queue.put(7)
),那么某个线程将立即打印该数字。你知道吗
这就是为什么我添加了最后一个打印行print("\n CPU_C " + str(CPU_number) + ": the next line is the return")
,我注意到只有一个线程将终止。换句话说,当我运行上面的代码时,只有一个线程会打印“下一行是return”。你知道吗
奇怪的是,当我取下锁时,这个问题就消失了。没有锁,它工作得很好。你知道吗
我错过了什么?你知道吗
实际上,不仅仅只有一个线程会给出
the next line is the return
。可以是1到8之间的任何地方。你知道吗在我的处决中,有时我得到1,3,4,5,6,7或1,2,3,4,5,6,7或1,4,5,6,7或只有5,6,7等
你有比赛条件。你知道吗
竞争条件在
while
检查not my_queue.empty()
和lock.acquire()
之间本质上,
.empty()
可以给您一个“it is not empty”的值,但是在您获得锁之前,其他的东西可能已经把这个值取出来了。因此,您需要检查锁内的这些东西。你知道吗下面是一个更安全的实现:
注意:在您当前的代码中,因为您只获得值—它始终是一个拦截器,即对于整个循环,一次只有一个线程。理想的情况是:
相关问题 更多 >
编程相关推荐