{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Threading und Forking kombinieren\n", "\n", "Das Mischen von Multiprocessing und Threading ist generell problematisch und ein Rezept für Deadlocks.\n", "\n", "Der folgende Code wurde 2016 unter https://bugs.python.org/issue27422 im Python Bugtracker eingetragen:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2026-05-21T21:28:02.119926Z", "iopub.status.busy": "2026-05-21T21:28:02.119670Z", "iopub.status.idle": "2026-05-21T21:28:02.240026Z", "shell.execute_reply": "2026-05-21T21:28:02.239619Z", "shell.execute_reply.started": "2026-05-21T21:28:02.119906Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "starting 0\n", "starting 1\n", "starting 2\n", "starting 3\n", "starting 4\n", "starting 5\n", "starting 6\n", "starting 7\n", "starting 8\n", "starting 9\n", "starting 10\n", "starting 11\n", "starting 12\n", "starting 13\n", "starting 14\n", "starting 15\n", "finished 9\n", "finished 0\n", "running 0\n", "running 9\n", "running 5\n", "running 4\n", "running 2\n", "running 3\n", "finished 5\n", "running 10\n", "finished 4\n", "finished 2\n", "finished 3\n", "running 8\n", "finished 10\n", "finished 8\n", "running 14\n", "running 15\n", "running 6\n", "running 7\n", "running 1\n", "finished 14\n", "finished 7\n", "running 11\n", "finished 6\n", "finished 15\n", "finished 1\n", "finished 11\n", "running 12\n", "running 13\n", "finished 12\n", "finished 13\n" ] } ], "source": [ "import multiprocessing\n", "\n", "from concurrent.futures import ThreadPoolExecutor\n", "\n", "\n", "def run(arg):\n", " print(f\"starting {arg}\")\n", " p = multiprocessing.Process(target=print, args=(\"running\", arg))\n", " p.start()\n", " p.join()\n", " print(f\"finished {arg}\")\n", "\n", "\n", "if __name__ == \"__main__\":\n", " n = 16\n", " tests = range(n)\n", " with ThreadPoolExecutor(n) as pool:\n", " for _r in pool.map(run, tests):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ü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." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.13 Kernel", "language": "python", "name": "python313" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }