Thema: concurrency
-
Abbruch und Fristen in Go mit context.Context
Einen context.Context von der eingehenden Anfrage durch jeden Aufruf reichen, der blockieren kann, mit WithTimeout oder WithCancel abgeleitete Kindkontexte erzeugen, die Cancel-Funktion immer aufrufen und in Schleifen ctx.Done() prüfen, damit ein Verbindungsabbruch des Clients oder eine Frist den gesamten Baum von Goroutinen stoppt, statt sie weiterlaufen zu lassen.
-
Wann asyncio hilft und wann nicht
asyncio führt viele E/A-lastige Aufgaben auf einem Thread aus, indem es an await-Punkten pausiert; es beschleunigt CPU-lastigen Code nicht, und blockierende Aufrufe innerhalb von Coroutinen legen die gesamte Event-Loop lahm.
-
Transaktionsisolationsstufen in der Praxis
Read Committed, Repeatable Read und Serializable tauschen Nebenläufigkeit gegen Konsistenz; zu wissen, welche Anomalien jede Stufe zulässt, entscheidet, wann explizite Sperren oder Wiederholungsversuche nötig sind.
-
Zwischen Threads, Prozessen und asyncio für eine Python-Arbeitslast wählen
Zuerst den Hot Path klassifizieren: Warten auf I/O passt zu asyncio (viele Verbindungen, asynchrone Bibliotheken) oder zu einem Thread-Pool (wenige blockierende Aufrufe); reine Python-CPU-Arbeit braucht Prozesse oder einen Free-Threaded-Build; nativer Code, der das GIL freigibt, kann Threads nutzen. Jeden Pool begrenzen, die Prozess-Startmethode explizit wählen und den Abschaltpfad schreiben.
-
Read-after-Write mit zurückgegebenen Revisionen verifizieren
Ein Schreiben über seinen stabilen Identifikator und seine Revision bestätigen, ohne eine neuere gleichzeitige Aktualisierung mit dem genauen eingereichten Inhalt zu verwechseln.
-
Veraltete Schreib-Tokens als Signal zum erneuten Lesen behandeln
Nach einer fehlgeschlagenen Schreib-Vorbedingung erholen, indem erneut gelesen und die beabsichtigte Änderung gegen die aktuelle Version neu aufgebaut wird.
-
Bei welcher Arbeitslast übertrifft der Free-Threaded-CPython-Build einen Prozess-Pool für einen gemischten E/A- und CPU-Dienst?
Offene Frage: Der Free-Threaded-Build entfernt den GIL, fügt aber Overhead im Einzelthread-Betrieb hinzu und kann beim Import einer nicht vorbereiteten Extension auf den GIL zurückfallen, während Prozess-Pools für Pickling und Speicherverdopplung bezahlen; bei welchen Verhältnissen von CPU-Zeit zu Wartezeit, welchen Working Sets und welchen Kernzahlen liefert ein Thread-Pool auf dem Free-Threaded-Build mehr Durchsatz pro Kern?
-
C#-async/await-Stolpersteine: Sync-over-Async, async void und ConfigureAwait
Die klassischen Fehler in asynchronem C#-Code sind das Blockieren auf einem Task mit .Result, .Wait() oder GetAwaiter().GetResult() (Deadlocks unter einem Single-Thread-SynchronizationContext, Thread-Pool-Erschöpfung auf Servern), async-void-Methoden, deren Ausnahmen nicht abgefangen werden können, und ein falsch gesetztes ConfigureAwait(false), das in allgemeine Bibliotheken gehört und nicht in Anwendungscode.
-
Virtuelle Threads in Java im Überblick: was sich ändert und was nicht
JEP 444 (JDK 21) führt virtuelle Threads ein: günstige Threads, die vom JDK auf einen kleinen Pool von Carrier-Platform-Threads eingeplant werden und die bei den meisten JDK-I/O-Operationen beim Blockieren aushängen, sodass Thread-pro-Anfrage-Code ohne asynchronen Stil skaliert. Sie sind nicht schneller, dürfen nie gepoolt werden, und bis JEP 491 (JDK 24) pinnte ein Blockieren innerhalb von synchronized den Carrier.
-
Ablaufende Leases für verteilte Jobs verwenden
Einen zurückgewonnenen Job vor einem verspäteten früheren Worker schützen, mittels Besitzprüfungen und einem monoton steigenden Fencing-Token.
-
Der GIL: Was er serialisiert und was er nicht sicher macht
Der Global Interpreter Lock lässt jeweils nur einen Thread Python-Bytecode ausführen und schützt die internen Strukturen des Interpreters, nicht die Invarianten des Programms: Read-Modify-Write-Abläufe wie counter += 1 oder Check-then-Set auf einem Dict benötigen weiterhin einen threading.Lock. Free-Threaded-Builds halten dieselbe Regel ein.
-
Goroutinen, Channels und das sync-Package: Nebenläufigkeit in Go im Überblick
Eine go-Anweisung führt einen Funktionsaufruf nebenläufig auf einem günstigen, wachsenden Stack aus; Channels übertragen Werte zwischen Goroutinen und blockieren, bis beide Seiten bereit sind; sync.WaitGroup, Mutex und Once decken die Fälle ab, in denen das Teilen von Speicher einfacher ist. Ein Data Race ist ein Fehler, dessen Ausgang das Memory Model nur teilweise einschränkt, und der -race-Detektor ist das Werkzeug, um ihn zu finden.
-
Zustand nach einer Jev-Entscheidung und vor einer Nebenwirkung erneut validieren
Verhindern, dass eine Entscheidung über einen früheren Anwendungszustand blind angewendet wird, nachdem sich der betroffene Datensatz, die Berechtigungen oder die Strategie geändert haben.
-
Go-Race-Detector-Abdeckung: ein sauberer Lauf sagt nichts über unausgeführte Pfade aus
Die Ergebnisse von go test -race mit den tatsächlich durchlaufenen nebenläufigen Pfaden verknüpfen, einschliesslich Start und Beendigung.
-
Tokio-Send-Fehler: den über await hinweg erhaltenen Zustand untersuchen
Ein gestartetes Future reparieren, indem untersucht wird, was die Suspendierung überdauert, statt unsichere Trait-Implementierungen hinzuzufügen.
-
Nebenläufigkeit pro Host und Konto begrenzen
Gleichzeitige Werkzeugaufrufe getrennt von der Anfragerate steuern, mit begrenzten Warteschlangen und einer abbruchsicheren Freigabe von Permits.
-
ThreadSanitizer-Triage: den fehlenden Synchronisationsvertrag wiederherstellen
Beide widersprüchlichen Zugriffspfade lesen und die Eigentums- oder Synchronisationsregel reparieren, die sie verbindet.
Maschinenlesbar: JSON