Gibt es eine Möglichkeit, dieses Problem von einer Lösung mit mehreren Threads anstelle eines einzelnen Threads zu profitieren?
In einem Interview wurde ich gebeten, ein Problem mit mehreren Threads zu lösen. Es scheint mir, dass die mehreren Threads keinen Nutzen bringt.
Hier ist das Problem:
Sie erhalten einen Absatz, der n Wörter enthält, Sie erhalten m Threads. Was Sie tun müssen, ist, dass jeder Thread ein Wort drucken und die Steuerung an den nächsten Thread übergeben soll. Auf diese Weise druckt jeder Thread weiterhin ein Wort. Falls der letzte Thread kommt, sollte er den ersten Thread aufrufen. Der Druckvorgang wird wiederholt, bis alle Wörter in einem Absatz gedruckt wurden. Schließlich sollten alle Threads ordnungsgemäß beendet werden. Welche Art von Synchronisation wird verwendet?
Ich bin der festen Überzeugung, dass wir hier keine Vorteile aus den Threads ziehen können, glaube aber, dass der Interviewer versucht, meine Synchronisationsfähigkeiten zu messen. Vermisse ich etwas in diesem Problem, das mehrere Threads wertvoll machen würde?
Keine Notwendigkeit von Code, nur ein paar Gedanken. Ich werde es selbst umsetzen.
quelle
Antworten:
Es klingt für mich, als würden Sie zu einer Semaphorlösung geführt. Semaphoren werden verwendet, um einem anderen Thread zu signalisieren, dass er an der Reihe ist. Sie werden viel seltener verwendet als Mutexe, weshalb sie meiner Meinung nach eine gute Interviewfrage sind. Es ist auch der Grund, warum das Beispiel erfunden zu sein scheint.
Grundsätzlich würden Sie
m
Semaphoren erstellen . Jeder Threadx
wartet auf ein Semaphorx
und postet dann auf ein Semaphor,x+1
nachdem er seine Sache erledigt hat. Im Pseudocode:quelle
Meiner Meinung nach ist dies eine fantastische Interviewfrage - zumindest unter der Annahme, dass (1) der Kandidat über fundierte Kenntnisse im Threading verfügt und (2) der Interviewer über fundierte Kenntnisse verfügt und die Frage verwendet, um den Kandidaten zu untersuchen. Es ist immer möglich, dass der Interviewer nach einer bestimmten, engen Antwort suchte, aber ein kompetenter Interviewer sollte Folgendes suchen:
Dieser letzte Punkt ist meiner Meinung nach der wichtigste. Aus meiner Erfahrung heraus wird es wiederum exponentiell schwieriger, Thread-Code zu debuggen, wenn das Threading mit der Anwendungslogik gemischt wird (sehen Sie sich zum Beispiel alle Swing-Fragen zu SO an). Ich glaube, dass der beste Multithread-Code als in sich geschlossener Single-Thread-Code mit klar definierten Übergaben geschrieben wird.
In diesem Sinne würde mein Ansatz darin bestehen, jedem Thread zwei Warteschlangen zuzuweisen: eine für die Eingabe und eine für die Ausgabe. Der Thread blockiert beim Lesen der Eingabewarteschlange, entfernt das erste Wort aus der Zeichenfolge und übergibt den Rest der Zeichenfolge an die Ausgabewarteschlange. Einige der Merkmale dieses Ansatzes:
Dennoch gibt es noch viele Grauzonen, die ein kompetenter Interviewer untersuchen kann:
Wenn Sie Erfahrung in der gleichzeitigen Programmierung haben, sprechen Sie möglicherweise über einige Frameworks (z. B. Akka für Java / Scala), die bereits diesem Modell folgen.
quelle
Interviewfragen sind manchmal reine Trickfragen, die Sie über das Problem nachdenken lassen sollen, das Sie zu lösen versuchen. Das Stellen von Fragen zu einer Frage ist ein wesentlicher Bestandteil bei der Lösung eines Problems, sei es in der realen Welt oder in einem Interview. Im Internet gibt es eine Reihe von Videos, in denen erläutert wird, wie Fragen in technischen Interviews beantwortet werden können (insbesondere Google und möglicherweise Microsoft).
Wenn Sie sich Interviews mit diesem Gedankenmuster nähern, werden Sie jedes Interview für jedes Unternehmen bombardieren, für das es sich lohnt, zu arbeiten.
Wenn Sie nicht der Meinung sind, dass Sie viel gewinnen (wenn überhaupt durch das Einfädeln), sagen Sie ihnen dies. Sagen Sie ihnen, warum Sie glauben, dass es keinen Nutzen gibt. Besprechen Sie sich mit ihnen. Technische Interviews sollen eine offene Diskussionsplattform sein. Sie können am Ende etwas zu lernen , wie man es kann nützlich sein. Versuchen Sie nicht einfach blindlings, etwas umzusetzen, das Ihnen Ihr Interviewer gesagt hat.
quelle
Token Sie zuerst den Absatz mit den entsprechenden Trennzeichen und fügen Sie die Wörter zu einer Warteschlange hinzu.
Erstellen Sie N Threads und speichern Sie sie in einem Thread-Pool.
Durchlaufen Sie den Thread-Pool und starten Sie den Thread. Warten Sie,
bis sich der Thread anschließt. Starten Sie den nächsten Thread, sobald der erste Thread endet und so weiter.
Jeder Thread sollte nur die Warteschlange abfragen und ausdrucken.
Wenn alle Threads im Thread-Pool verwendet wurden, beginnen Sie am Anfang des Pools.
quelle
Wie Sie sagten, glaube ich nicht, dass dieses Szenario von Threading stark profitiert, wenn überhaupt. Es ist wahrscheinlich langsamer als eine Single-Thread-Implementierung.
Meine Antwort wäre jedoch, dass jeder Thread in einer engen Schleife versucht, auf eine Sperre zuzugreifen, die den Zugriff auf den Wort-Array-Index steuert. Jeder Thread greift nach der Sperre, ruft den Index ab, ruft das entsprechende Wort aus dem Array ab, druckt es aus, erhöht den Index und gibt die Sperre frei. Der Thread wird beendet, wenn sich der Index am Ende des Arrays befindet.
Etwas wie das:
Ich denke, dies sollte den einen Thread nach dem anderen erfordern, aber die Reihenfolge der Threads ist nicht garantiert. Ich bin gespannt auf weitere Lösungen.
quelle
Verwenden Sie Condition Wait / Signal-APIs, um dieses Problem zu beheben.
Nehmen wir an, der erste Thread wählt 1 Wort und in der Zwischenzeit warten alle Threads auf ein Signal. Der erste Thread druckt das erste Wort und generiert ein Signal für den nächsten Thread und der zweite Thread druckt das zweite Wort und generiert ein Signal für den dritten Thread und so weiter.
quelle
[Die hier verwendeten Begriffe beziehen sich möglicherweise auf POSIX-Threads.]
Es sollte auch möglich sein, einen FIFO-Mutex zu verwenden, um dieses Problem zu lösen.
Wo zu verwenden:
Angenommen, zwei Threads T1 und T2 versuchen, einen kritischen Abschnitt auszuführen. Beide haben außerhalb dieses kritischen Abschnitts nicht viel zu tun und halten die Sperren für eine Weile. Somit kann T1 sperren, ausführen und entsperren und T2 zum Aufwecken signalisieren. Bevor T2 jedoch aufgeweckt und die Sperre aktiviert werden konnte, ruft T1 die Sperre erneut ab und führt sie aus. Auf diese Weise muss T2 möglicherweise sehr lange warten, bis es tatsächlich die Sperre erhält, oder auch nicht.
Wie es funktioniert / Wie implementiert man:
Habe einen Mutex zum Aufstecken. Initialisieren Sie Thread-spezifische Daten (TSD) für jeden Thread für einen Knoten, der die Thread-ID und das Semaphor enthält. Haben Sie auch zwei Variablen - besessen (WAHR oder FALSCH oder -1), Eigentümer (Eigentümer-Thread-ID). Stellen Sie außerdem eine Warteschlange für Kellner und einen Zeiger waiterLast bereit, der auf den letzten Knoten in der Warteschlange für Kellner verweist.
Sperrbetrieb:
entsperren betrieb:
quelle
Interessante Frage. Hier ist meine Lösung in Java, die SynchronousQueue verwendet, um einen Rendezvous-Kanal zwischen Threads zu erstellen:
quelle
Ich würde sagen, dass diese Art von Frage sehr schwer zu beantworten ist, weil sie nach dem besten Weg fragt, etwas völlig Dummes zu tun. Mein Gehirn funktioniert einfach nicht so. Es kann keine Lösung für dumme Fragen finden. Mein Gehirn würde sofort sagen, dass unter diesen Umständen die Verwendung mehrerer Threads sinnlos ist, also würde ich einen einzelnen Thread verwenden.
Ich würde sie dann bitten, entweder eine reale Frage zum Thema Threading zu stellen oder mir ein reales Beispiel für ernsthaftes Threading zu geben.
quelle