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
import subprocess
import sys

from concurrent.futures import ThreadPoolExecutor


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


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

Ü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.