python中的While循环在包含

2024-04-20 01:39:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在学习使用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”。你知道吗

奇怪的是,当我取下锁时,这个问题就消失了。没有锁,它工作得很好。你知道吗

我错过了什么?你知道吗


Tags: the代码importlocknumberreturnqueuemy
1条回答
网友
1楼 · 发布于 2024-04-20 01:39:26

实际上,不仅仅只有一个线程会给出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”的值,但是在您获得锁之前,其他的东西可能已经把这个值取出来了。因此,您需要检查锁内的这些东西。你知道吗

下面是一个更安全的实现:

import threading
import queue
import time

my_queue = queue.Queue()

lock = threading.Lock()

for i in range(50):
    my_queue.put(i)

def something_useful(CPU_number):
    while True:
        lock.acquire()
        if not my_queue.empty():
            print("CPU_C " + str(CPU_number) + ": " + str(my_queue.get()))
            lock.release()
        else:
            lock.release()
            break

    print("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()

注意:在您当前的代码中,因为您只获得值—它始终是一个拦截器,即对于整个循环,一次只有一个线程。理想的情况是:

if not my_queue.empty():
    val = my_queue.get()
    lock.release()
    print("CPU_C " + str(CPU_number) + ": " + str(val))
    heavy_processing(val)  # While this is going on another thread can read the next val

相关问题 更多 >