【问题标题】:How to use Queue with threading properly如何正确使用带有线程的队列
【发布时间】:2021-12-27 07:09:36
【问题描述】:

我是队列和线程的新手,请帮助下面的代码,这里我正在尝试执行函数 hd,我需要多次运行该函数,但只有在一次运行之后完成

import queue
import threading
import time

fifo_queue = queue.Queue()

def hd():
    print("hi")
    time.sleep(1)
    print("done")


for i in range(3):
    cc = threading.Thread(target=hd)
    fifo_queue.put(cc)
    cc.start()

电流输出

hi
hi
hi
donedonedone

预期输出

hi
done   
hi
done
hi
done​

【问题讨论】:

  • “我需要多次运行该函数,但只能在一次运行完成后” 这不是违背了并行处理的目的吗?看起来您可能想要一个简单的循环?
  • 您需要 mutex lock 检查 this 以获取示例用法。
  • 感谢 mozway 是的,我知道常规 for 循环将在这种情况下工作,只是徘徊我如何与 Queue 一起使用,所以以后如果需要我可以将它与复杂功能一起使用

标签: python python-3.x multithreading


【解决方案1】:

您可以将Semaphore 用于您的目的

信号量管理一个内部计数器,每次调用acquire() 递减,每次调用release() 递增。计数器永远不会低于零;当acquire() 发现它为零时,它会阻塞,等待其他线程调用release()。

信号量的默认值为1

类 threading.Semaphore(value=1)

所以一次只有一个线程处于活动状态:

import queue
import threading
import time

fifo_queue = queue.Queue()

semaphore = threading.Semaphore()


def hd():
    with semaphore:
        print("hi")
        time.sleep(1)
        print("done")


for i in range(3):
    cc = threading.Thread(target=hd)
    fifo_queue.put(cc)
    cc.start()
hi
done
hi
done
hi
done

正如 cmets RLock 中提到的 @user2357112supportsMonica 将是更安全的选择

类 threading.RLock

这个类实现了可重入锁对象。重入锁必须由获取它的线程释放。一旦一个线程获得了可重入锁,同一个线程可以再次获得它而不会阻塞;线程每次获取它时都必须释放它一次。

import queue
import threading
import time

fifo_queue = queue.Queue()

lock = threading.RLock()


def hd():
    with lock:
        print("hi")
        time.sleep(1)
        print("done")


for i in range(3):
    cc = threading.Thread(target=hd)
    fifo_queue.put(cc)
    cc.start()

【讨论】:

  • 可能值得指出的是,信号量的默认值为 1 ;)
  • @mozway 好点,谢谢。添加到答案
  • 如果你只是要使用这样的信号量,锁会更合适,threading.Lockthreading.RLock。 (RLock 通常是最安全的默认值,可以避免LockSemaphore 可能发生的几类错误。)
  • @Eugenij:如果一个线程试图释放另一个线程持有的RLock,你会得到一个RuntimeError,让你知道问题所在。如果您尝试使用LockSemaphore,发布会默默成功,隐藏错误。
  • 另外,如果一个线程试图获取一个它已经持有的锁,使用 Lock 或 1-count Semaphore,它会默默地死锁。使用RLock,第二次获取成功,并且只有在线程解锁两次后才会解锁锁。这对于您将执行 with lock: ... 的函数委托给也需要执行 with lock: ... 的其他函数的情况很重要。
【解决方案2】:

请把 print("down") 放在睡觉前。 它会正常工作。 原因: 你的程序会这样做: 线程1
: 打印
睡觉
打印 但是当线程处于休眠状态时,其他线程将工作并打印它们的第一个命令。 以我的方式,线程将写入第一个,写入第二个,然后进入睡眠状态并等待其他线程出现。

【讨论】:

    猜你喜欢
    • 2015-07-30
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多