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 sys
import multiprocessing
import subprocess
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 0
starting 1
starting 2
starting 3
starting 4
starting 5
starting 6
starting 7
starting 8
starting 9
starting 10
starting 11starting 12
starting 13
starting 14
starting 15

running 15
running 6
finished 15
finished 6finished 9

finished 11
finished 7
running 9
running 7
running 11
finished 15
running 8
finished 15
running 10
finished 15
running 1
finished 15
running 4
finished 15
running 12
finished 15
running 0
running 2
finished 15
running 14
running 3
finished 15
running 13
running 5
finished 10finished 1finished 4finished 8



finished 12
finished 0
finished 14
finished 2
finished 3
finished 13
finished 5

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