Threading und Forking kombinieren

Das Mischen von Multiprocessing und Threading ist generell problematisch und ein Rezept für Deadlocks.

Der folgende Code wurde 2016 unter https://bugs.python.org/issue27422 im Python Bugtracker eingetragen:

[1]:
import multiprocessing

from concurrent.futures import ThreadPoolExecutor


def run(arg):
    print(f"starting {arg}")
    p = multiprocessing.Process(target=print, args=("running", arg))
    p.start()
    p.join()
    print(f"finished {arg}")


if __name__ == "__main__":
    n = 16
    tests = range(n)
    with ThreadPoolExecutor(n) as pool:
        for _r in pool.map(run, tests):
            pass
starting 0
starting 1
starting 2
starting 3
starting 4
starting 5
starting 6
starting 7
starting 8
starting 9
starting 10
starting 11
starting 12
starting 13
starting 14
starting 15
finished 9
finished 0
running 0
running 9
running 5
running 4
running 2
running 3
finished 5
running 10
finished 4
finished 2
finished 3
running 8
finished 10
finished 8
running 14
running 15
running 6
running 7
running 1
finished 14
finished 7
running 11
finished 6
finished 15
finished 1
finished 11
running 12
running 13
finished 12
finished 13

Üblicherweise empfiehlt sich Threading nach dem Fork, nicht vorher. Andernfalls werden die beim Ausführen der Threads verwendeten Locks über die Prozesse dupliziert. Stirbt einer dieser Prozesse mit einem Lock, so geraten alle anderen Prozesse mit diesem Lock in einen Deadlock.