{ "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": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "starting 0starting 1\n", "\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", "running 5\n", "finished 5\n", "running 4\n", "running 3\n", "finished 3\n", "finished 4\n", "running 1\n", "running 2\n", "running 7\n", "finished 2\n", "finished 1\n", "running 6\n", "finished 7\n", "finished 6\n", "running 12\n", "running 0\n", "running 8\n", "running 14\n", "finished 12\n", "finished 0\n", "finished 8\n", "finished 14\n", "running 10\n", "running 9\n", "finished 10\n", "finished 9\n", "running 13\n", "running 11\n", "finished 13\n", "finished 11\n", "running 15\n", "finished 15\n" ] } ], "source": [ "import multiprocessing\n", "import subprocess\n", "import sys\n", "\n", "from concurrent.futures import ThreadPoolExecutor\n", "\n", "\n", "def run(arg):\n", " print(\"starting %s\" % arg)\n", " p = multiprocessing.Process(target=print, args=(\"running\", arg))\n", " p.start()\n", " p.join()\n", " print(\"finished %s\" % 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.11 Kernel", "language": "python", "name": "python311" }, "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.11.4" }, "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": 2 }