如何确保一个进程在其他进程之前启动?

how to make sure one process start before other process?

如何确保一个进程先于另一个进程启动?

背景: 我在两个独立的进程中进行计算(每个进程 运行 在一个循环中)。但是对于一个过程中的计算,我需要另一个过程的计算结果。第一个想法可能是:为什么不同步呢? 但是这个计算比另一个计算运行得更快。如果没有可用的新结果,它应该继续使用最后一个可用值。

示例代码:

from multiprocessing import Process, Queue
import time
import random

queue = Queue()

def some_calculation():
    # this is slower
    time.sleep(2)
    return random.randint(0, 10)

def some_other_calculation(required):
    # this is faster
    time.sleep(0.5)
    return required + random.randint(0, 10)

def first_target(queue):
    while True:
        # doing some computations
        res = some_calculation()
        queue.put(res)

def second_target(queue):
    res_list= []
    # req = 5 as an initial guess might also work, but lets
    # assume this is not an option
    while True:
        try:
            req = queue.get(block=False)
        except:
            print('no new value available, reuse old value')
        res = some_other_calculation(req)
        res_list.append(res)
        print('results so far:', res_list)

if __name__ == '__main__':
    proc1 = Process(target=first_target, args=(queue,))
    proc2 = Process(target=second_target, args=(queue,))
    proc1.start()
    # time.sleep(3) here everything works fine, but is there
    # maybe a more elegant solution?
    proc2.start()
        

除了休眠或为 req 预定义一个值之外,有没有办法确保这个进程真正在另一个进程之前启动?

非常感谢您的提前帮助!

这个想法是 second_target 启动一个线程,该线程将在队列上发出阻塞 get 调用,从而不断地用最新的可用值更新 req 变量。 second_target 还需要对 some_calculation 进行初始同步调用以获取其初始值 req 以大大简化逻辑。为了演示目的,我还将 second_target 中的无限 while True 循环替换为更有限的循环,以便程序终止:

from multiprocessing import Process, Queue
import time
import random
from threading import Thread


def some_calculation():
    # this is slower
    time.sleep(2)
    return random.randint(0, 10)

def some_other_calculation(required):
    # this is faster
    time.sleep(0.5)
    return required + random.randint(0, 10)

def first_target(queue):
    while True:
        # doing some computations
        res = some_calculation()
        queue.put(res)

def second_target(queue):
    def monitor_queue():
        nonlocal queue, req
        while True:
            req = queue.get()

    res_list= []
    req = some_calculation() # Call it synchronously for initial value
    last_req = req
    Thread(target=monitor_queue, daemon=True).start()
    for _ in range(10): # for testing purposes so we terminate:
    #while True:
        if req == last_req:
            print('no new value available, reuse old value')
        else:
            print('got a new value')
            last_req = req
        res = some_other_calculation(req)
        res_list.append(res)
        print('results so far:', res_list)

if __name__ == '__main__':
    queue = Queue()
    p = Process(target=first_target, args=(queue,), daemon=True)
    p.start()
    second_target(queue)

打印:

no new value available, reuse old value
results so far: [5]
got a new value
results so far: [5, 2]
no new value available, reuse old value
results so far: [5, 2, 2]
no new value available, reuse old value
results so far: [5, 2, 2, 7]
no new value available, reuse old value
results so far: [5, 2, 2, 7, 11]
got a new value
results so far: [5, 2, 2, 7, 11, 11]
no new value available, reuse old value
results so far: [5, 2, 2, 7, 11, 11, 13]
no new value available, reuse old value
results so far: [5, 2, 2, 7, 11, 11, 13, 13]
got a new value
results so far: [5, 2, 2, 7, 11, 11, 13, 13, 7]
no new value available, reuse old value
results so far: [5, 2, 2, 7, 11, 11, 13, 13, 7, 11]