Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
而python中的循环不';当它包含锁时,t结束_Python_Multithreading_Queue_Locking - Fatal编程技术网

而python中的循环不';当它包含锁时,t结束

而python中的循环不';当它包含锁时,t结束,python,multithreading,queue,locking,Python,Multithreading,Queue,Locking,我目前正在学习在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.a

我目前正在学习在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\U C”+str(CPU\U编号)+”:下一行是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
check
not my_queue.empty()
lock.acquire()之间

本质上,
.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

实际上,不只是一个线程会给出
,下一行是返回值。可以是1到8之间的任意位置

在我的处决中,有时我得到1,3,4,5,6,7或1,2,3,4,5,6,7或1,4,5,6,7或只有5,6,7等

你有比赛条件

竞赛条件介于
while
check
not my_queue.empty()
lock.acquire()之间

本质上,
.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

谢谢,我没意识到这一点。知道如何修复它吗?比如说:“一旦一个线程获得了锁,后续获取它的尝试就会被阻止,直到它被释放;任何线程都可能释放它。”谢谢,我没有意识到这一点。你知道如何修复它吗?比如说:“一旦一个线程获得了锁,后续获取它的尝试就会阻塞,直到它被释放;任何线程都可以释放它。”一般来说,使用锁访问队列在某种程度上违背了
队列
的目的。您也可以在代码中使用列表或
collections.deque
而不是
queue.queue
。请参见一个不带锁的示例。如何结束线程(队列.Empty:
)取决于您的问题。常见的替代方法是一些停止标志(您可以检查它,而不是简单地返回)或在队列上放置一些“停止”项以停止线程(这样您就不再需要
get
超时)。一般来说,使用锁访问队列会有点违背
队列的目的。您也可以在代码中使用列表或
collections.deque
而不是
queue.queue
。请参见一个不带锁的示例。如何结束线程(队列.Empty:
)取决于您的问题。常用的替代方法是一些停止标志(您可以检查它,而不是简单地返回),或者在队列上放置一些“停止”项来停止线程(这样您就不再需要
get
的超时)。