Heim  >  Artikel  >  Java  >  Was sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?

Was sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?

WBOY
WBOYnach vorne
2023-04-23 23:07:061044Durchsuche

Was sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?

1. Was ist der Unterschied zwischen synchronisierten modifizierten gewöhnlichen Methoden und statischen Methoden? Was ist Sichtbarkeit?

Objektsperren werden für Objektinstanzmethoden oder eine Objektinstanz verwendet, und Klassensperren werden für statische Methoden einer Klasse oder Klassenobjekte einer Klasse verwendet. Wir wissen, dass es viele Objektinstanzen einer Klasse geben kann, jede Klasse jedoch nur ein Klassenobjekt hat, sodass sich die Objektsperren verschiedener Objektinstanzen nicht gegenseitig stören, es jedoch nur eine Klassensperre für jede Klasse gibt.
Eine Sache, die beachtet werden muss, ist, dass die Klassensperre tatsächlich nur eine konzeptionelle Sache ist und nicht tatsächlich existiert. Die Klassensperre sperrt tatsächlich das entsprechende Klassenobjekt jeder Klasse. Klassensperren und Objektsperren stören sich auch nicht gegenseitig.
Sichtbarkeit bedeutet, dass, wenn mehrere Threads auf dieselbe Variable zugreifen und ein Thread den Wert der Variablen ändert, andere Threads den geänderten Wert sofort sehen können.
Da alle Operationen an Variablen durch Threads im Arbeitsspeicher ausgeführt werden müssen und Variablen im Hauptspeicher nicht direkt gelesen und geschrieben werden können, befinden sich die gemeinsam genutzten Variablen V zunächst in ihrem eigenen Arbeitsspeicher und werden dann mit dem Hauptspeicher synchronisiert. Allerdings wird es nicht rechtzeitig in den Hauptspeicher geleert, sondern es entsteht ein gewisser Zeitunterschied. Offensichtlich ist die Operation von Thread A an der Variablen V zu diesem Zeitpunkt für Thread B nicht mehr sichtbar.
Um das Problem der Sichtbarkeit gemeinsamer Objekte zu lösen, können wir das Schlüsselwort volatile oder lock verwenden.

2. Welche Kategorien von Schlössern gibt es?

Was sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?

3. Das Prinzip der CAS-sperrenfreien Programmierung.

Aktuelle Prozessoren unterstützen grundsätzlich die CAS()-Anweisung, aber die von jedem Hersteller implementierten Algorithmen sind unterschiedlich. Jeder CAS-Operationsprozess enthält drei Operatoren: eine Speicheradresse V und einen erwarteten Wert B. Während des Betriebs. Wenn der an dieser Adresse gespeicherte Wert gleich dem erwarteten Wert A ist, wird der Wert an der Adresse dem neuen Wert B zugewiesen, andernfalls wird keine Operation ausgeführt.
Die Grundidee von CAS besteht darin, dass, wenn der Wert an dieser Adresse dem erwarteten Wert entspricht, ihr ein neuer Wert zugewiesen wird. Andernfalls wird nichts anderes getan, als den ursprünglichen Wert zurückzugeben. Loop CAS besteht darin, Cas-Operationen kontinuierlich in einer Schleife auszuführen, bis sie erfolgreich sind. Wir können auch über drei große Probleme mit CAS sprechen.

4. Implementierungsprinzip von ReentrantLock.

Ein Thread kann wiederholt jeden Codeblock betreten, der durch eine Sperre synchronisiert wird, die er bereits besitzt, und ReentrantLock sind beide wiedereintretende Sperren. In Bezug auf die Implementierung bestimmt jedes Mal, wenn ein Thread eine Sperre erhält, ob der Thread, der die Sperre erhält, er selbst ist, und akkumuliert einfach den Zähler. Jedes Mal, wenn die Sperre aufgehoben wird, wird der Zähler dekrementiert, bis der Rechner auf Null zurückkehrt, was dies anzeigt Der Thread wurde komplett freigegeben. Die unterste Ebene wird mithilfe von AQS in JUC implementiert.

5. AQS-Prinzip.

ist das Grundgerüst zum Erstellen von Sperren oder anderen Synchronisierungskomponenten wie ReentrantLock, ReentrantReadWriteLock und CountDownLatch, die auf AQS-Basis implementiert werden. Es verwendet eine int-Mitgliedsvariable, um den Synchronisationsstatus darzustellen, und schließt die Warteschlangenarbeit von Ressourcenerfassungsthreads über die integrierte FIFO-Warteschlange ab. Es handelt sich um eine Variantenimplementierung der CLH-Warteschlangensperre. Es können zwei Synchronisierungsmethoden erreicht werden: exklusiv und gemeinsam genutzt.
Die Hauptmethode zur Verwendung von AQS ist die Vererbung. Unterklassen verwalten den Synchronisierungsstatus, indem sie AQS erben und seine abstrakten Methoden implementieren. Das Design des Synchronisierers basiert auf dem Vorlagenmethodenmuster. Wenn wir also unsere eigene Synchronisierungstoolklasse implementieren möchten um mehrere davon abzudecken, z. B. tryAcquire, tryReleaseShared usw.
Der Zweck dieses Designs besteht darin, dass Synchronisierungskomponenten (z. B. Sperren) benutzerorientiert sind. Es definiert die Schnittstelle, über die Benutzer mit Synchronisierungskomponenten interagieren können (z. B. um zwei Threads den parallelen Zugriff zu ermöglichen) und die Implementierungsdetails zu verbergen ist für den Implementierer von Sperren, der die Implementierung von Sperren vereinfacht und zugrunde liegende Vorgänge wie Synchronisationsstatusverwaltung, Thread-Warteschlangen, Warten und Aufwachen abschirmt. Dadurch werden die Bereiche effektiv isoliert, auf die sich Benutzer und Implementierer konzentrieren müssen.
Intern verwaltet AQS einen gemeinsamen Ressourcenstatus und verwendet den integrierten FIFO, um die Warteschlangenarbeit der Ressourcenbeschaffungsthreads abzuschließen. Die Warteschlange besteht nacheinander aus Knotenknoten. Jeder Knotenknoten verwaltet eine vorherige Referenz und eine nächste Referenz, die auf seinen eigenen Vorgänger- bzw. Nachfolgerknoten verweisen und eine doppelt verknüpfte Liste mit zwei Enden bilden.

6. Das Prinzip von Synchronized und der Unterschied zu ReentrantLock.

synchronisiertes (dieses) Prinzip: Beinhaltet zwei Anweisungen: Monitorenter, Monitorexit. Aus den Dekompilierungsergebnissen der Synchronisierungsmethode geht hervor, dass die Synchronisierung der Methode nicht durch die Anweisungen Monitorenter und Monitorexit erreicht wird Bei der gewöhnlichen Methode gibt es einen zusätzlichen ACC_SYNCHRONIZED-Bezeichner im Konstantenpool.
Die JVM implementiert die Methodensynchronisation basierend auf dieser Kennung: Wenn die Methode aufgerufen wird, prüft die aufrufende Anweisung, ob das ACC_SYNCHRONIZED-Zugriffsflag der Methode gesetzt ist. Wenn es gesetzt ist, ruft der Ausführungsthread zuerst den Monitor ab und führt ihn dann aus Nachdem die Methode erfolgreich erfasst wurde, wird der Monitor freigegeben, nachdem die Methode ausgeführt wurde. Während der Methodenausführung kann kein anderer Thread dasselbe Monitorobjekt erneut abrufen.

7. Welche Optimierungen hat Synchronized vorgenommen?

Einführung von Technologien wie Spin-Lock, adaptivem Spin-Lock, Lock-Eliminierung, Lock-Coarsing, Bias-Lock, Lightweight-Lock, Escape-Analyse und anderen Technologien, um die Kosten von Lock-Operationen zu senken.

  • Escape-Analyse: Wenn nachgewiesen wird, dass ein Objekt einer Methode oder einem Thread nicht entkommt, kann diese Variable optimiert werden:

  • Synchronisationseliminierung: Synchronisationseliminierung, wenn ein Objekt nicht entkommt einen Thread, dann können die Synchronisationsmaßnahmen für diese Variable eliminiert werden.

  • Sperrenbeseitigung und grobe Sperrenbeseitigung: Wenn der Laufzeit-Compiler der virtuellen Maschine erkennt, dass es bei Code, der zur Laufzeit synchronisiert werden muss, wahrscheinlich nicht zu einer Konkurrenz gemeinsamer Daten kommen wird, werden diese Sperren entfernt.

  • Vergröberung der Sperre: Zusammenführen benachbarter Codeblöcke mit derselben Sperre. Durch die Eliminierung bedeutungsloser Sperrenerfassung und -freigabe kann die Programmausführungsleistung verbessert werden.

8. Der Unterschied und Umfang synchronisierter statischer und nicht statischer Sperren.

Objektsperren werden für Objektinstanzmethoden oder eine Objektinstanz verwendet. Klassensperren werden für statische Methoden einer Klasse oder Klassenobjekte einer Klasse verwendet. Wir wissen, dass es viele Objektinstanzen einer Klasse geben kann, jede Klasse jedoch nur ein Klassenobjekt hat, sodass sich die Objektsperren verschiedener Objektinstanzen nicht gegenseitig stören, es jedoch nur eine Klassensperre für jede Klasse gibt.
Eine Sache, die beachtet werden muss, ist, dass die Klassensperre tatsächlich nur eine konzeptionelle Sache ist und nicht tatsächlich existiert. Die Klassensperre sperrt tatsächlich das entsprechende Klassenobjekt jeder Klasse. Klassensperren und Objektsperren stören sich auch nicht gegenseitig.

9. Kann Volatilität die Thread-Sicherheit garantieren? Was macht es auf DCL?

Es gibt keine Garantie für die Rolle von DCL: Volatile stellt die Sichtbarkeit und Ordnung geänderter Variablen sicher und stellt sicher, dass im Singleton-Modus die Ausführungsreihenfolge beim Erstellen eines Objekts

  1. Zuweisung von Speicherplatz

  2. sein muss Instanziieren Sie die Objektinstanz.

  3. Verweisen Sie auf die Instanzreferenz auf den zugewiesenen Speicherplatz. Zu diesem Zeitpunkt verfügt die Instanz über eine Speicheradresse und ist nicht mehr null. Dadurch wird sichergestellt, dass die Instanz entweder null oder bereits ein vollständig initialisiertes Objekt ist.

10. Was ist der Unterschied zwischen volatil und synchronisieren?

volatile ist der leichteste Synchronisationsmechanismus. Volatile garantiert die Sichtbarkeit, wenn verschiedene Threads mit dieser Variablen arbeiten. Das heißt, wenn ein Thread den Wert einer Variablen ändert, ist der neue Wert sofort für andere Threads sichtbar. Volatile kann jedoch die Atomizität von Vorgängen nicht garantieren, sodass zusammengesetzte Schreibvorgänge unter Multithreads zu Thread-Sicherheitsproblemen führen.
Das Schlüsselwort synchronisiert kann zum Ändern von Methoden oder in Form von synchronisierten Blöcken verwendet werden. Es stellt hauptsächlich sicher, dass mehrere Threads gleichzeitig nur einen Thread in einer Methode oder einem synchronisierten Block haben können. und Exklusivität, auch bekannt als integrierte Schließmechanismen.

11. Was ist ein Daemon-Thread? Wie verlässt man einen Thread?

Der Daemon-Thread ist ein Support-Thread, da er hauptsächlich für die Hintergrundplanung und Support-Arbeit im Programm verwendet wird. Dies bedeutet, dass die Java Virtual Machine beendet wird, wenn in einer Java Virtual Machine keine Nicht-Daemon-Threads vorhanden sind. Ein Thread kann als Daemon-Thread festgelegt werden, indem Thread.setDaemon(true) aufgerufen wird. Wir verwenden es im Allgemeinen nicht. Der Garbage-Collection-Thread ist beispielsweise der Daemon-Thread.
        Thread-Unterbrechung : Entweder ist die Ausführung des Laufs abgeschlossen oder es wird eine nicht behandelte Ausnahme ausgelöst, die dazu führt, dass der Thread vorzeitig beendet wird. Die dem Thread-Thread entsprechenden APIs zum Anhalten, Fortsetzen und Stoppen von Vorgängen sind suspend(), resume() und stop(). Diese APIs sind jedoch veraltet, das heißt, ihre Verwendung wird nicht empfohlen. Weil es dazu führt, dass das Programm in einem unsicheren Zustand arbeitet. Die Aussetzung der Sicherheit besteht darin, dass andere Threads den Interrupt-Vorgang unterbrechen, indem sie die Methode interrupt () eines Threads A aufrufen, und der unterbrochene Thread bestimmt, ob er durch den Thread unterbrochen wird, indem er die Methode Thread.interrupted( verwendet. ) wird verwendet, um zu bestimmen, ob der aktuelle Thread unterbrochen ist, aber Thread.interrupted() schreibt auch das Interrupt-Flag-Bit auf false um.

12. Der Unterschied zwischen Schlafen, Warten und Nachgeben. Wie weckt der Wartethread ihn?

yield()-Methode: bewirkt, dass der aktuelle Thread den CPU-Besitz aufgibt, die Zeit für die Aufgabe kann jedoch nicht festgelegt werden. Die Sperrressource wird nicht freigegeben. Alle Threads, die yield() ausführen, können vom Betriebssystem erneut ausgewählt und sofort nach Eintritt in den Bereitschaftszustand ausgeführt werden.
Nach dem Aufruf von yield() und sleep() wird die vom aktuellen Thread gehaltene Sperre nicht aufgehoben.
Nach dem Aufruf der Methode wait () wird die vom aktuellen Thread gehaltene Sperre aufgehoben, und nachdem der aktuelle Thread aktiviert wurde, konkurriert er erneut um die Sperre. Der Code hinter der Methode wait wird erst ausgeführt, nachdem die Sperre aktiviert wurde konkurrierte.
Warten wird normalerweise für die Interaktion zwischen Threads verwendet, Ruhe wird normalerweise verwendet, um die Ausführung anzuhalten, und die Methode yield() bewirkt, dass der aktuelle Thread den CPU-Besitz aufgibt.
Der Wartethread verwendet notify/notifyAll() zum Aufwachen.

13. Ist der Schlaf unterbrechbar?

sleep selbst unterstützt Interrupts. Wenn der Thread während des Ruhezustands unterbrochen wird, wird eine Interrupt-Ausnahme ausgelöst.

14. Thread-Lebenszyklus.

Der Status von Threads in Java ist in 6 Typen unterteilt:

  1. Initial (NEU): Ein neues Thread-Objekt wird erstellt, aber die start()-Methode wurde noch nicht aufgerufen.

  2. Run (RUNNABLE): In Java-Threads werden die beiden Zustände „Bereit“ und „Laufen“ im Allgemeinen als „Laufen“ bezeichnet. Nachdem das Thread-Objekt erstellt wurde, rufen andere Threads (z. B. der Haupt-Thread) die start()-Methode des Objekts auf. Der Thread in diesem Zustand befindet sich im ausführbaren Thread-Pool und wartet darauf, von der Thread-Planung ausgewählt zu werden, um das Recht zur Nutzung der CPU zu erhalten. Er befindet sich zu diesem Zeitpunkt im Bereitschaftszustand. Der Thread im Bereitschaftszustand wechselt nach Erhalt der CPU-Zeitscheibe in den laufenden Zustand (läuft).

  3. BLOCKED: Zeigt an, dass der Thread in der Sperre blockiert ist.

  4. Warten: Der Thread, der diesen Status erreicht, muss darauf warten, dass andere Threads bestimmte Aktionen ausführen (Benachrichtigung oder Unterbrechung).

  5. Timeout-Warten (TIMED_WAITING): Dieser Zustand unterscheidet sich von WAITING, er kann nach der angegebenen Zeit von selbst zurückkehren.

  6. TERMINATED: Zeigt an, dass die Ausführung des Threads abgeschlossen ist.

Was sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?

15. Was ist ThreadLocal?

ThreadLocal ist eine spezielle Variable in Java. ThreadLocal stellt für jeden Thread eine Kopie der Variablen bereit, sodass nicht jeder Thread zu einem bestimmten Zeitpunkt auf dasselbe Objekt zugreift, wodurch die Datenfreigabe durch mehrere Threads isoliert wird.
In Bezug auf die interne Implementierung verfügt jeder Thread über eine ThreadLocalMap, die zum Speichern einer Kopie der Variablen verwendet wird, die jedem Thread gehören.

16. Grundprinzipien des Thread-Pools.

Während des Entwicklungsprozesses kann die rationelle Nutzung von Thread-Pools drei Vorteile bringen.
Erstens: Reduzieren Sie den Ressourcenverbrauch.
Zweitens: Reaktionsgeschwindigkeit verbessern.
Drittens: Verbessern Sie die Thread-Verwaltbarkeit.

  1. Wenn die aktuell ausgeführten Threads kleiner als corePoolSize sind, erstellen Sie einen neuen Thread, um die Aufgabe auszuführen (beachten Sie, dass für die Ausführung dieses Schritts eine globale Sperre erforderlich ist).

  2. Wenn die laufenden Threads gleich oder größer als corePoolSize sind, fügen Sie die Aufgabe zur BlockingQueue hinzu.

  3. Wenn die Aufgabe nicht zur BlockingQueue hinzugefügt werden kann (die Warteschlange ist voll), erstellen Sie einen neuen Thread, um die Aufgabe zu verarbeiten.

  4. Wenn das Erstellen eines neuen Threads dazu führt, dass der aktuell laufende Thread die maximale PoolSize überschreitet, wird die Aufgabe abgelehnt und die Methode RejectedExecutionHandler.rejectedExecution() aufgerufen.

Siebzehn. Es gibt drei Threads T1, T2 und T3.

Kann mit der Join-Methode implementiert werden.

Das obige ist der detaillierte Inhalt vonWas sind die relevanten Wissenspunkte zu Java-Thread-Interviewfragen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen