Ich habe fast 3 Jahre Erfahrung mit dem Schreiben von Webanwendungen in Java unter Verwendung von MVC-Frameworks (wie Struts). Ich habe bisher noch nie Multithread-Code geschrieben, obwohl ich Code für große Einzelhandelsketten geschrieben habe.
Ich bekomme während eines Interviews ein paar Fragen zum Thema Multithreading und beantworte sie normalerweise (meist einfache Fragen). Ich habe mich deshalb gefragt, wie wichtig Multithreading im aktuellen Branchenszenario ist.
multithreading
user2434
quelle
quelle
Antworten:
Das ist extrem wichtig.
Wichtiger ist es jedoch zu verstehen, dass Multithreading nur eine Möglichkeit ist, das Asynchronitätsproblem zu lösen. Die technische Umgebung, in der derzeit viele Leute Software schreiben, unterscheidet sich von der historischen Softwareentwicklungsumgebung (von monolithischen Anwendungen, die Stapelberechnungen durchführen) in zweierlei Hinsicht:
Many-Core-Maschinen sind mittlerweile weit verbreitet. Es ist nicht mehr zu erwarten, dass Taktraten oder Transistordichten um Größenordnungen zunehmen. Der Preis für Berechnungen wird weiter sinken, er wird jedoch aufgrund vieler Parallelitäten sinken. Wir werden einen Weg finden müssen, diese Kraft auszunutzen.
Computer sind heute stark vernetzt, und moderne Anwendungen sind darauf angewiesen, dass sie umfassende Informationen aus einer Vielzahl von Quellen abrufen können.
Aus rechnerischer Sicht laufen diese beiden Faktoren im Wesentlichen auf die gleiche Kernidee hinaus: Informationen werden zunehmend asynchron verfügbar sein . Ob die Informationen, die Sie benötigen, auf einem anderen Chip in Ihrer Maschine oder auf einem Chip in der ganzen Welt berechnet werden, spielt keine Rolle. So oder so sitzt Ihr Prozessor da und verbrennt Milliarden von Zyklen pro Sekunde, um auf Informationen zu warten, wenn er nützliche Arbeit leisten könnte.
Was jetzt zählt und was in Zukunft noch wichtiger sein wird, ist also nicht Multithreading an sich, sondern der Umgang mit Asynchronität . Multithreading ist nur ein Weg, dies zu tun - ein komplizierter, fehleranfälliger Weg, der nur noch komplizierter und fehleranfälliger wird, wenn schwache Speichermodell-Chips immer häufiger eingesetzt werden.
Die Herausforderung für Anbieter von Tools besteht darin, für unsere Kunden eine bessere Lösung als Multithreading zu finden, um mit der künftig verwendeten asynchronen Infrastruktur fertig zu werden.
quelle
concurrency
ist wichtiger als dasasynchronous
Verhalten. Sie können asynchrone ohne Parallelität (dh mehrere Threads auf einer einzelnen Kern-CPU) haben,asynchronous
ist kein semantischer Ersatz fürconcurrency
.Es wird immer wichtiger, da moderne Prozessoren immer mehr Kerne haben. Vor einem Jahrzehnt hatten die meisten vorhandenen Computer nur einen einzigen Prozessor, daher war Multithreading nur bei High-End-Serveranwendungen wichtig. Heutzutage haben sogar einfache Laptops Multicore-Prozessoren. In einigen Jahren werden sogar mobile Geräte ... Es wird also immer mehr Code benötigt, um die potenziellen Leistungsvorteile der Parallelität zu nutzen und in einer Multithread-Umgebung ordnungsgemäß ausgeführt zu werden.
quelle
Im Allgemeinen ist Multithreading bereits sehr wichtig und wird erst in den nächsten Jahren an Bedeutung gewinnen (wie Péter Török betonte) - so werden Prozessoren in absehbarer Zukunft skalieren (mehr Kerne statt höherer MHz) .
In Ihrem Fall scheinen Sie jedoch hauptsächlich mit Webanwendungen zu arbeiten. Aufgrund der Art und Weise, wie Ihr Webserver Anforderungen für jeden Benutzer verarbeitet (dh parallel), sind Webanwendungen von Natur aus multithreaded. Während es für Sie wahrscheinlich wichtig ist, Parallelität und Thread-Sicherheit zu verstehen (insbesondere beim Umgang mit Caches und anderen gemeinsam genutzten Daten), bezweifle ich, dass Sie in zu vielen Fällen den Webanwendungscode intern (dh mit mehreren Workern) in mehrere Threads einbinden können Threads pro Anfrage). In diesem Sinne denke ich, dass es für einen Webentwickler nicht unbedingt notwendig ist, ein Experte für Multithreading zu sein. Es wird oft in Interviews gefragt, weil es ein ziemlich kniffliges Thema ist und weil viele Interviewer nur 10 Minuten vor Ihrer Ankunft ein paar Fragen googeln.
quelle
Multithreading ist ein roter Hering. Multithreading ist ein Implementierungsdetail für das eigentliche Problem, nämlich die Parallelität . Nicht alle Thread-Programme sind aufgrund von Sperren gleichzeitig aktiv und was nicht.
Threads sind nur ein Modell und ein Implementierungsmuster für die Implementierung von
concurrent
Programmen.Zum Beispiel können Sie hoch skalierbare und fehlertolerante Software schreiben, ohne Multithreading in Sprachen wie Erlang durchführen zu müssen.
quelle
Gut, um die Interviews zu bestehen, kann Multithreading sehr wichtig sein. Ich zitiere mich selbst : "Wenn ich Kandidaten für unser Team interviewe, stelle ich nebenläufige Fragen, nicht weil diese Fähigkeiten für unser Projekt wichtig sind (diese sind es nicht ), sondern weil sie es mir irgendwie erleichtern, allgemeine Sprachkenntnisse zu bewerten, die wir verwenden ..."
quelle
In der heutigen Softwareumgebung ist es für die meisten Branchen und Anwendungen von entscheidender Bedeutung, zu verstehen, wie Threading zur Verbesserung der Leistung eingesetzt werden kann.
Zumindest sollte das Verständnis der mit der Parallelität verbundenen Probleme gegeben sein.
Der offensichtliche Hinweis, dass nicht alle Anwendungen oder Umgebungen davon profitieren können, gilt beispielsweise für viele eingebettete Systeme. Es scheint jedoch, als ob der Atom-Prozessor (et al.) Daran arbeitet, dies zu ändern (leichte Multicores werden immer häufiger).
quelle
Klingt so, als würden Sie bereits Multithread-Code schreiben.
Die meisten Java-Webanwendungen können mehrere Anforderungen gleichzeitig verarbeiten und verwenden dazu mehrere Threads.
Daher würde ich sagen, dass es wichtig ist, zumindest die Grundlagen zu kennen.
quelle
Es ist immer noch wichtig in Situationen, in denen Sie es brauchen, aber wie viele andere Dinge in der Entwicklung ist es das richtige Werkzeug für den richtigen Job. Ich war 3 Jahre lang ohne das Einfädeln zu berühren, jetzt hat praktisch alles, was ich tue, einen Grund. Bei Multi-Core-Prozessoren besteht nach wie vor ein großer Bedarf an Threading, aber alle herkömmlichen Gründe sind weiterhin gültig. Sie möchten weiterhin reaktionsschnelle Schnittstellen und möchten weiterhin in der Lage sein, sich mit der Synchronisierung zu befassen und gleichzeitig mit anderen Dingen umzugehen.
quelle
Kurze Antwort: Sehr.
Längere Antwort: Elektronische (Transistor-basierte) Computer nähern sich schnell den physikalischen Grenzen der Technologie. Es wird immer schwieriger, mehr Takte aus jedem Kern herauszupressen, während die Wärmeerzeugung und die Quanteneffekte mikroskopischer Schaltungen verwaltet werden (Schaltungspfade sind auf modernen Chips bereits so eng beieinander angeordnet, dass ein Effekt namens "Quantentunneling" ein Elektron erzeugen kann "jump the tracks" von einem Stromkreis zum anderen, ohne die richtigen Bedingungen für einen herkömmlichen Lichtbogen zu benötigen); Daher konzentrieren sich praktisch alle Chiphersteller darauf, dass jeder Takt mehr leisten kann, indem mehr "Ausführungseinheiten" in jede CPU eingebaut werden. Anstatt dass der Computer nur eine Aktion pro Uhr ausführt, kann er 2, 4 oder sogar 8 ausführen. Intel hat "HyperThreading", Dies teilt im Grunde einen CPU-Kern in zwei logische Prozessoren auf (mit einigen Einschränkungen). Praktisch alle Hersteller stecken mindestens zwei separate CPU-Kerne in einen CPU-Chip, und der aktuelle Goldstandard für Desktop-CPUs liegt bei vier Kernen pro Chip. Acht sind möglich, wenn zwei CPU-Chips verwendet werden, es gibt Server-Mainboards, die für "Quad-Quad-Core" -Prozessoren (16 EUs plus optionales HT) ausgelegt sind, und die nächste Generation von CPUs wird wahrscheinlich sechs oder acht pro Chip haben.
Das Ergebnis all dessen ist, dass Sie es dem Computer ermöglichen müssen, Ihr Programm zu "teilen und zu erobern", damit er die Vorteile der Computer nutzen kann, die an Rechenleistung zunehmen. Verwaltete Sprachen haben mindestens einen GC-Thread, der die Speicherverwaltung separat von Ihrem Programm verwaltet. Einige haben auch "Transition" -Threads, die COM / OLE-Interop verarbeiten (sowohl für den Schutz der verwalteten "Sandbox" als auch für die Leistung). Darüber hinaus müssen Sie jedoch überlegen, wie Ihr Programm mehrere Aufgaben gleichzeitig ausführen kann, und Ihr Programm mit Funktionen versehen, mit denen Teile des Programms asynchron verarbeitet werden können. Windows und Windows-Benutzer erwarten praktisch, dass Ihr Programm lange, komplizierte Aufgaben in Hintergrundthreads ausführt. Die Benutzeroberfläche Ihres Programms (das im Hauptthread des Programms ausgeführt wird) reagiert auf die Windows-Nachrichtenschleife. Natürlich sind Probleme mit parallelisierbaren Lösungen (wie das Sortieren) natürliche Kandidaten, aber es gibt eine begrenzte Anzahl von Problemtypen, die von der Parallelisierung profitieren.
quelle
Nur eine Warnung zum Multithreading: Mehr Threads bedeuten keine bessere Effizienz. Wenn sie nicht ordnungsgemäß verwaltet werden, können sie das System verlangsamen. Scalas Schauspieler verbessern Javas Threading und maximieren die Systemnutzung (erwähnt als Java-Entwickler).
EDIT: Hier sind einige Dinge zu beachten, die die Nachteile von Multithreading betreffen:
Auch diese Verbindung könnte eine Hilfe in etwa gleich sein.
quelle
In leistungskritischen Bereichen, in denen die Leistung nicht von Drittanbieter-Code stammt, sondern von unserem eigenen Code, würde ich Dinge aus der CPU-Perspektive eher in dieser Reihenfolge berücksichtigen (die GPU ist ein Platzhalter, den ich gewonnen habe) geht nicht rein):
Beachten Sie, dass diese Liste nicht nur von der Wichtigkeit abhängt, sondern auch von vielen anderen Faktoren wie den Auswirkungen auf die Wartung, wie einfach sie sind (wenn nicht, sollten Sie dies im Voraus berücksichtigen), ihren Interaktionen mit anderen auf der Liste usw.
Speichereffizienz
Die meisten sind vielleicht überrascht, dass ich die Speichereffizienz gegenüber der algorithmischen Wahl gewählt habe. Dies liegt daran, dass die Speichereffizienz mit allen vier anderen Elementen in dieser Liste interagiert und die Berücksichtigung häufig eher in der Kategorie "Design" als in der Kategorie "Implementierung" erfolgt. Zugegebenermaßen gibt es hier ein kleines Problem mit Hühnern oder Eiern, da für das Verständnis der Speichereffizienz häufig alle 4 Elemente auf der Liste berücksichtigt werden müssen, während für alle 4 anderen Elemente auch die Speichereffizienz berücksichtigt werden muss. Dennoch ist es das Herzstück von allem.
Wenn wir beispielsweise eine Datenstruktur benötigen, die sequentiellen Zugriff in linearer Zeit und zeitlich konstante Einfügungen nach hinten und nichts anderes für kleine Elemente bietet, wäre die naive Wahl, nach der wir hier greifen, eine verknüpfte Liste. Das ignoriert die Speichereffizienz. Wenn wir die Speichereffizienz in der Mischung berücksichtigen, wählen wir in diesem Szenario am Ende zusammenhängendere Strukturen aus, wie z. B. anwachsende Array-basierte Strukturen oder zusammenhängende Knoten (z. B. einer, der 128 Elemente in einem Knoten speichert), die miteinander verbunden sind, oder zumindest eine verknüpfte Liste, die von einem Pool-Allokator unterstützt wird. Diese haben trotz der gleichen algorithmischen Komplexität einen dramatischen Vorteil. Ebenso wählen wir häufig die schnelle Sortierung eines Arrays anstelle der Sortierung nach Zusammenführung, obwohl die algorithmische Komplexität aufgrund der Speichereffizienz minderwertig ist.
Ebenso können wir kein effizientes Multithreading haben, wenn unsere Speicherzugriffsmuster so detailliert und verstreut sind, dass wir das Ausmaß der falschen Freigabe maximieren und gleichzeitig auf den detailliertesten Codeebenen sperren. Die Speichereffizienz multipliziert also die Effizienz von Multithreading. Dies ist eine Grundvoraussetzung, um das Beste aus den Threads herauszuholen.
Jedes einzelne Element in der Liste hat eine komplexe Interaktion mit Daten, und die Konzentration auf die Darstellung von Daten trägt letztendlich zur Speichereffizienz bei. Jedes einzelne dieser oben genannten Elemente kann mit einer unangemessenen Art der Darstellung oder des Zugriffs auf Daten in Konflikt geraten.
Ein weiterer Grund, warum die Speichereffizienz so wichtig ist, besteht darin, dass sie auf die gesamte Codebasis angewendet werden kann . Im Allgemeinen ist es ein Zeichen dafür, dass man sich einen Profiler zulegen muss, wenn man sich vorstellt, dass sich Ineffizienzen durch kleine Teile der Arbeit hier und da ansammeln. Felder mit geringer Latenz oder solche, die sich mit sehr begrenzter Hardware befassen, werden auch nach der Profilerstellung tatsächlich Sitzungen finden, die keine eindeutigen Hotspots (nur zeitweise über den gesamten Bereich verteilt) in einer Codebasis anzeigen, die bei der Zuweisung, beim Kopieren und bei der Erstellung von Profilen eklatant ineffizient ist Zugriff auf Speicher. In der Regel ist dies das einzige Mal, dass eine gesamte Codebasis Leistungsproblemen ausgesetzt ist, die zu einer Reihe neuer Standards führen können, die in der gesamten Codebasis angewendet werden, und die Speichereffizienz steht häufig im Mittelpunkt.
Algorithmisch
Dies ist so ziemlich selbstverständlich, da die Auswahl in einem Sortieralgorithmus den Unterschied zwischen einer massiven Eingabe, deren Sortierung Monate in Anspruch nimmt, und Sekunden in Anspruch nimmt. Es macht den größten Einfluss von allen, wenn die Wahl zwischen beispielsweise wirklich unterdurchschnittlichen quadratischen oder kubischen Algorithmen und einem linearen oder zwischen linearen und logarithmischen oder konstanten Algorithmus besteht, zumindest bis wir 1.000.000 Kernmaschinen haben (in diesem Fall Speicher) Effizienz würde noch wichtiger werden).
Es steht jedoch nicht ganz oben auf meiner persönlichen Liste, da jeder, der auf seinem Gebiet kompetent ist, wissen würde, wie man eine Beschleunigungsstruktur für das Abtöten von Kegelstümpfen verwendet Ein Radix-Baum für Präfix-basierte Suchanfragen ist Babymaterial. Ohne diese Grundkenntnisse in dem Bereich, in dem wir arbeiten, würde die algorithmische Effizienz sicherlich an die Spitze rücken, aber die algorithmische Effizienz ist oftmals trivial.
Auch das Erfinden neuer Algorithmen kann in einigen Bereichen eine Notwendigkeit sein (z. B. bei der Netzverarbeitung musste ich Hunderte erfinden, da sie entweder vorher nicht existierten oder die Implementierung ähnlicher Funktionen in anderen Produkten proprietäre Geheimnisse waren, die nicht in einem Papier veröffentlicht wurden ). Sobald wir jedoch den Teil zur Problemlösung hinter uns haben und einen Weg finden, die richtigen Ergebnisse zu erzielen, und wenn Effizienz zum Ziel wird, können wir nur noch darüber nachdenken, wie wir mit Daten (Speicher) interagieren. Ohne die Speichereffizienz zu verstehen, kann der neue Algorithmus mit vergeblichen Anstrengungen, ihn zu beschleunigen, unnötig komplex werden, wenn nur die Speichereffizienz berücksichtigt werden muss, um einen einfacheren und eleganteren Algorithmus zu erhalten.
Schließlich liegen Algorithmen eher in der Kategorie "Implementierung" als in der Kategorie "Speichereffizienz". Sie sind im Nachhinein oft einfacher zu verbessern, selbst wenn zunächst ein suboptimaler Algorithmus verwendet wird. Beispielsweise wird ein schlechterer Bildverarbeitungsalgorithmus oft nur an einer lokalen Stelle in der Codebasis implementiert. Es kann später gegen ein besseres ausgetauscht werden. Wenn jedoch alle Bildverarbeitungsalgorithmen an eine
Pixel
Schnittstelle gebunden sind, die eine suboptimale Speicherdarstellung aufweist, aber die einzige Möglichkeit zur Korrektur darin besteht, die Darstellung mehrerer Pixel (und nicht eines einzigen) zu ändern, sind wir häufig SOL und müssen die Codebasis in Richtung eines vollständig umschreibenImage
Schnittstelle. Das Gleiche gilt für das Ersetzen eines Sortieralgorithmus - normalerweise handelt es sich um ein Implementierungsdetail, während eine vollständige Änderung der zugrunde liegenden Darstellung der zu sortierenden Daten oder der Art und Weise, wie sie durch Nachrichten geleitet werden, möglicherweise eine Neugestaltung der Schnittstellen erforderlich macht.Multithreading
Multithreading ist eine schwierige Aufgabe im Hinblick auf die Leistung, da es sich um eine Optimierung auf Mikroebene handelt, die auf Hardwareeigenschaften abzielt, aber unsere Hardware skaliert tatsächlich in diese Richtung. Bereits habe ich Gleichaltrige, die 32 Kerne haben (ich habe nur 4).
Mulithreading gehört jedoch zu den gefährlichsten Mikrooptimierungen, die einem Fachmann wahrscheinlich bekannt sind, wenn der Zweck darin besteht, Software zu beschleunigen. Die Racebedingung ist so ziemlich der tödlichste Fehler, der möglich ist, da sie so unbestimmt ist (möglicherweise wird sie nur einmal alle paar Monate auf dem Computer eines Entwicklers zu einem äußerst ungünstigen Zeitpunkt außerhalb eines Debugging-Kontexts angezeigt, wenn überhaupt). Es hat also die wohl negativste Beeinträchtigung der Wartbarkeit und potenziellen Korrektheit von Code unter all diesen, zumal Fehler im Zusammenhang mit Multithreading selbst bei sorgfältigsten Tests leicht zu übersehen sind.
Trotzdem wird es so wichtig. Auch wenn es angesichts der Anzahl der Kerne, die wir jetzt haben, nicht immer besser ist als die Speichereffizienz (die manchmal die Dinge hundertmal schneller macht), sehen wir immer mehr Kerne. Selbst bei Computern mit 100 Kernen würde ich die Speichereffizienz immer noch ganz oben auf die Liste setzen, da die Thread-Effizienz ohne sie im Allgemeinen nicht möglich ist. Ein Programm kann auf einer solchen Maschine hundert Threads verwenden und trotzdem langsam sein, ohne effiziente Speicherdarstellung und Zugriffsmuster (die mit Sperrmustern verknüpft sind).
SIMD
SIMD ist auch ein bisschen umständlich, da die Register tatsächlich breiter werden, mit Plänen, noch breiter zu werden. Ursprünglich sahen wir 64-Bit-MMX-Register, gefolgt von 128-Bit-XMM-Registern, die 4 SPFP-Operationen parallel ausführen können. Jetzt sehen wir 256-Bit-YMM-Register, die 8 parallel ausführen können. Und es gibt bereits Pläne für 512-Bit-Register, die 16 parallel zulassen würden.
Diese würden mit der Effizienz von Multithreading interagieren und sich vervielfachen. SIMD kann jedoch die Wartbarkeit genauso beeinträchtigen wie Multithreading. Auch wenn Fehler, die mit ihnen zusammenhängen, nicht unbedingt so schwer zu reproduzieren und zu beheben sind wie ein Deadlock oder eine Race-Bedingung, ist die Portabilität umständlich und es muss sichergestellt werden, dass der Code auf jedem Computer ausgeführt werden kann (und die entsprechenden Anweisungen basierend auf den Hardware-Funktionen verwendet werden) peinlich.
Eine andere Sache ist, dass Compiler heutzutage normalerweise keinen fachmännisch geschriebenen SIMD-Code schlagen, aber naive Versuche leicht bestehen. Sie werden möglicherweise so weit verbessert, dass wir sie nicht mehr manuell ausführen müssen oder zumindest nicht mehr so manuell, dass sie inhärenten Code oder reinen Assembler-Code schreiben (vielleicht nur eine kleine menschliche Anleitung).
Auch hier ist SIMD ohne ein für die vektorisierte Verarbeitung effizientes Speicherlayout nutzlos. Am Ende wird nur ein Skalarfeld in ein breites Register geladen, um nur eine Operation auszuführen. Das Herzstück all dieser Elemente ist die Abhängigkeit von Speicherlayouts, um wirklich effizient zu sein.
Andere Optimierungen
Ich würde oft vorschlagen, dass wir heutzutage von "Mikro" sprechen, wenn das Wort andeutet, dass nicht nur der algorithmische Fokus überschritten wird, sondern auch Änderungen, die sich nur geringfügig auf die Leistung auswirken.
Häufig erfordert der Versuch, die Verzweigungsvorhersage zu optimieren, eine Änderung des Algorithmus oder der Speichereffizienz. Wenn dies z. B. nur durch Hinweise versucht wird und der Code für die statische Vorhersage neu angeordnet wird, wird die erstmalige Ausführung dieses Codes tendenziell nur verbessert, was die Auswirkungen in Frage stellt, wenn nicht oft völlig zu vernachlässigen.
Zurück zu Multithreading für Leistung
Wie wichtig ist Multithreading in einem Leistungskontext? Auf meinem 4-Core-Rechner können die Dinge idealerweise etwa fünfmal schneller gemacht werden (was ich mit Hyperthreading erreichen kann). Für meinen Kollegen mit 32 Kernen wäre das wesentlich wichtiger. Und es wird in den kommenden Jahren immer wichtiger.
Also ist es ziemlich wichtig. Es ist jedoch sinnlos, nur eine Reihe von Threads auf das Problem zu werfen, wenn die Speichereffizienz nicht ausreicht, um die sparsame Verwendung von Sperren zu ermöglichen, falsche Freigabe zu reduzieren usw.
Multithreading außerhalb der Leistung
Beim Multithreading geht es nicht immer nur um reine Leistung im Sinne eines einfachen Durchsatzes. Manchmal wird es verwendet, um eine Last sogar auf die möglichen Kosten des Durchsatzes auszugleichen, um die Reaktionsfähigkeit des Benutzers zu verbessern, oder um es dem Benutzer zu ermöglichen, mehr Multitasking auszuführen, ohne darauf zu warten, dass die Dinge abgeschlossen sind (z. B. Fortsetzen des Surfens beim Herunterladen einer Datei).
In diesen Fällen würde ich vorschlagen, dass Multithreading nach oben hin noch weiter ansteigt (möglicherweise sogar über die Speichereffizienz hinaus), da es dann eher um benutzerorientiertes Design geht, als darum, das Beste aus der Hardware herauszuholen. Es wird häufig das Interface-Design und die Art und Weise dominieren, wie wir unsere gesamte Codebasis in solchen Szenarien strukturieren.
Wenn wir nicht einfach eine enge Schleife parallelisieren, die auf eine massive Datenstruktur zugreift, wird Multithreading in die Kategorie "Design" eingestuft, und Design ist immer wichtiger als die Implementierung.
In diesen Fällen würde ich sagen, dass Multithreading im Vorfeld von entscheidender Bedeutung ist, noch mehr als die Speicherdarstellung und der Speicherzugriff.
quelle
Gleichzeitige und parallele Programmierung wird immer wichtiger. Threads sind nur ein Programmiermodell, um mehrere Dinge gleichzeitig zu erledigen (und nicht pseudo-parallel, wie es früher vor dem Aufkommen von Mehrkernprozessoren der Fall war). Multithreading wird (meiner Meinung nach) als komplex und gefährlich kritisiert, da Threads viele Ressourcen gemeinsam nutzen und der Programmierer dafür verantwortlich ist, dass sie zusammenarbeiten. Andernfalls kommt es zu Deadlocks, die nur schwer zu debuggen sind.
quelle
Da wir möglicherweise viele externe Anwendungen kontaktieren müssen, kann ein Hintergrundprozess auftreten, bei dem die Interaktion mit dem externen System länger dauert und der Endbenutzer nicht warten kann, bis der Prozess abgeschlossen ist. Multithreading ist also wichtig ..
Wir verwenden in unserer App zunächst das externe System. Wenn es nicht funktioniert, speichern wir die Anforderung in der Datenbank und spannen einen Thread auf, um den Vorgang in backgound abzuschließen. Kann auch in Batch-Operationen erforderlich sein.
quelle
In der Vergangenheit hatten die Menschen Probleme damit, Multithread-Programme von Hand zu erstellen. Sie mussten direkt mit allen Kernkomponenten (Threads, Semaphoren, Mutexe, Sperren usw.) arbeiten.
All diese Bemühungen führten zu Anwendungen, die durch Hinzufügen von zusätzlichem CPU zu einem einzelnen System skaliert werden konnten. Diese vertikale Skalierbarkeit ist begrenzt durch "Was ist der größte Server, den ich kaufen kann".
Heutzutage sehe ich eine Verlagerung hin zur Verwendung von mehr Frameworks und verschiedenen Designmodellen für das Software-Design. MapReduce ist ein solches Modell, das sich auf die Stapelverarbeitung konzentriert.
Das Ziel ist die horizontale Skalierung. Hinzufügen von mehr Standardservern, anstatt größere Server zu kaufen.
Trotzdem bleibt die Tatsache, dass es sehr wichtig ist, Multithread-Programme wirklich zu verstehen. Ich war in einer Situation, in der jemand eine Rennbedingung erstellt hat und wusste nicht einmal, was eine Rennbedingung ist, bis wir beim Testen merkwürdige Fehler bemerkten.
quelle
Meine Maschine hat 8 Kerne. Im Task-Manager werden 60 Prozesse ausgeführt. Einige, wie VS, verwenden bis zu 98 Threads. Outlook verwendet 26. Ich gehe davon aus, dass der größte Teil meines Arbeitsspeichers aus den Stapeln besteht, die jedem dieser inaktiven Threads zugewiesen sind.
Ich persönlich warte darauf, dass der 300-Core-Computer herauskommt, damit ich nicht warten muss, bis Outlook antwortet. Natürlich wird Outlook bis dahin 301 Threads verwenden.
Multithreading ist nur dann von Bedeutung, wenn Sie Systeme erstellen, die zu einem bestimmten Zeitpunkt der einzige wichtige Prozess auf dem Computer sind (z. B. Berechnungsmodule). Desktop-Apps würden dem Benutzer wahrscheinlich einen Gefallen tun, indem sie nicht jeden verfügbaren Kern verbrauchen. Web-Apps, die das Anforderungs- / Antwortmodell verwenden, sind von Natur aus multithreaded.
Es ist wichtig für Framework- und Sprachentwickler sowie für Back-End-Systemprogrammierer - weniger für Anwendungsentwickler. Es lohnt sich jedoch wahrscheinlich, einige grundlegende Konzepte wie das Sperren und Schreiben von asynchronem Code zu verstehen.
quelle