Wie kann die Fadensicherheit der Utility-Static-Methode gewährleistet werden?

Lesezeit: 8 Minuten

Benutzer-Avatar
Tapas Bose

Gibt es einen allgemeinen Weg oder Regeln, mit denen wir die Thread-Sicherheit von statischen Methoden sicherstellen können, die speziell in verschiedenen Utility-Klassen von Anwendungen verwendet werden? An dieser Stelle möchte ich ausdrücklich auf die Threadsicherheit von Webanwendungen hinweisen.

Es ist allgemein bekannt, dass statische Methoden mit unveränderlichen Objekten als Parameter Thread-sicher sind und veränderliche Objekte nicht.

Wenn ich eine Hilfsmethode für einige Manipulationen habe java.util.Date und diese Methode akzeptiert eine Instanz von java.util.Date, dann wäre diese Methode nicht threadsicher. Wie kann man es dann threadsicher machen, ohne die Art der Parameterübergabe zu ändern?

public class DateUtils {

    public static Date getNormalizeDate(Date date) {
        // some operations
    }   
}

Auch die Klasse javax.faces.context.FacesContext veränderlich? Ist es threadsicher, eine Instanz dieser Klasse an eine solche statische Hilfsmethode zu übergeben?

Diese Liste von Klassen, deren Instanzen als Parameter übergeben werden können oder nicht, könnte lang sein; Welche Punkte sollten wir also beim Schreiben von Codes für solche Utility-Klassen beachten?

  • Warum abstimmen und eine Anfrage zum Schließen? Ist es eine falsche Frage?

    – Tapas Bose

    17. Dezember 2012 um 9:01 Uhr

  • Haben Sie darüber nachgedacht, diese statische Methode zu erstellen? synchronized?

    – Andreas Logwinow

    17. Dezember 2012 um 9:02 Uhr

  • @AndrewLogvinov ja, das habe ich mir gedacht. Aber ich möchte keine Methode synchronisieren, ohne zu wissen, warum ich es tue. In welchen Situationen sollten wir eine statische Methode synchronisieren?

    – Tapas Bose

    17. Dezember 2012 um 9:04 Uhr

  • @TapasBose Diese letzte Kommentarfrage kann wahrscheinlich ein oder zwei Bücher hervorbringen. ich würde empfehlen Java-Parallelität in der Praxis.

    – Duncan Jones

    17. Dezember 2012 um 9:11 Uhr

  • Nun, Sie müssen Methoden (sowohl statische als auch Instanzen) synchronisieren, die auf veränderliche Variablen zugreifen. Im Falle von Utility-Klassen sehe ich keinen großen Bedarf darin, da sie zustandslos sein sollten.

    – Andreas Logwinow

    17. Dezember 2012 um 9:13 Uhr

Benutzer-Avatar
Duncan Jones

Es ist allgemein bekannt, dass statische Methoden mit unveränderlichen Objekten als Parameter Thread-sicher sind und veränderliche Objekte nicht.

Dem würde ich widersprechen. An eine Methode übergebene Argumente werden auf einem Stack gespeichert, was ein Thread-spezifisches Idiom ist.

Wenn Ihr Parameter ein veränderliches Objekt wie a Date dann müssen Sie sicherstellen, dass andere Threads es nicht gleichzeitig an anderer Stelle ändern. Aber das ist eine andere Sache, die nichts mit der Thread-Sicherheit Ihrer Methode zu tun hat.

Die Methode, die Sie gepostet haben, ist Thread-sicher. Sie behält keinen Staat bei und handelt nur mit ihren Argumenten.

Ich würde dir dringend empfehlen zu lesen Java-Parallelität in der Praxis, oder ein ähnliches Buch, das sich der Thread-Sicherheit in Java widmet. Es ist ein komplexes Thema, das nicht durch ein paar StackOverflow-Antworten angemessen behandelt werden kann.

  • @Duncan: Welche anderen Bücher zum Thema Multithreading kannst du empfehlen?

    – Gaurav

    7. Dezember 2018 um 11:20 Uhr

  • Es gibt Multithreading im Java-Kurs auf educative.io educative.io/collection/5307417243942912/…

    – Shrikant Prabhu

    14. Dezember 2018 um 18:56 Uhr

  • IMO, xyz-Buch lesen ist im Allgemeinen keine hilfreiche Antwort. Warum nicht auf die konkrete Fragestellung näher eingehen, anstatt ein ganzes Buch auf eine Person zu werfen?

    – MasterJoe

    1. Juli 2020 um 18:43 Uhr

Benutzer-Avatar
Assyrien

Da Ihre Klasse keine Mitgliedsvariablen enthält, ist Ihre Methode zustandslos (sie verwendet nur lokale Variablen und das Argument) und ist daher Thread-sicher.

Der Code, der es aufruft, ist möglicherweise nicht Thread-sicher, aber das ist eine andere Diskussion. Da Date beispielsweise nicht threadsicher ist, müssen Sie, wenn der aufrufende Code ein Date liest, das von einem anderen Thread geschrieben wurde, eine ordnungsgemäße Synchronisierung im Code zum Schreiben und Lesen von Date verwenden.

Angesichts der Struktur der JVM sind lokale Variablen, Methodenparameter und Rückgabewerte von Natur aus „threadsicher“. Instanzvariablen und Klassenvariablen sind jedoch nur dann Thread-sicher, wenn Sie Ihre Klasse entsprechend entwerfen. mehr hier

Ich sehe viele Antworten, aber keine, die wirklich auf den Grund hinweist.

Das kann man sich also so vorstellen: Immer wenn ein Thread erstellt wird, wird er mit seinem eigenen Stack erstellt (ich schätze, die Größe des Stacks zum Zeitpunkt der Erstellung beträgt ~ 2 MB). Jede Ausführung, die stattfindet, findet also tatsächlich im Kontext dieses Thread-Stacks statt. Jede Variable, die erstellt wird, lebt im Heap, aber ihre Referenz lebt im Stack, mit Ausnahme statischer Variablen, die nicht im Thread-Stack leben.

Jeder von Ihnen getätigte Funktionsaufruf wird tatsächlich auf den Thread-Stack geschoben, sei es statisch oder nicht statisch. Da die vollständige Methode auf den Stack geschoben wurde, lebt jede Variablenerstellung, die stattfindet, innerhalb des Stacks (wieder Ausnahmen sind statische Variablen) und nur für einen Thread zugänglich.

Alle Methoden sind also Thread-sicher, bis sie den Zustand einer statischen Variablen ändern.

Ich würde empfehlen, eine Kopie dieses (veränderlichen) Objekts zu erstellen, sobald die Methode gestartet wird, und die Kopie anstelle des ursprünglichen Parameters zu verwenden.

Etwas wie das

public static Date getNormalizeDate(Date date) {
    Date input = new Date(date.getTime());
    // ...
}

  • Das klingt gut für Date, ist aber für benutzerdefinierte Objekte nicht möglich, insbesondere wenn es sich um ein benutzerdefiniertes Objekt eines Drittanbieters handelt, das er nicht bearbeiten kann.

    – Saurabh Patil

    11. August 2017 um 10:36 Uhr

  • Wenn Sie im Falle eines Drittanbieters nicht klonen können, können Sie nicht viel tun, außer diesen Drittanbieter zu bitten, seine Klasseninstanzen Thread-sicher zu machen.

    – R. Kaja Mohideen

    9. Dezember 2018 um 8:00 Uhr

So denke ich darüber: Stellen Sie sich eine CampSite vor (das ist eine statische Methode). Als Camper kann ich eine Menge Gegenstände in meinem Rucksack mitbringen (das sind Argumente, die auf dem Stapel übergeben werden). Die CampSite bietet mir einen Ort, an dem ich mein Zelt und meinen Campingkocher usw. aufstellen kann, aber wenn die CampSite mir nur erlaubt, meine eigenen Objekte zu ändern, ist sie Thread-sicher. Die CampSite kann sogar Dinge aus dem Nichts erschaffen (FirePit firepit = new FirePit();), die ebenfalls auf dem Stack erstellt werden.

Ich kann jederzeit mit all meinen Gegenständen in meinem Rucksack verschwinden und einer der anderen Camper kann auftauchen und genau das tun, was sie beim letzten Verschwinden getan haben. Verschiedene Threads in dieser CampSite haben keinen Zugriff auf Objekte auf dem Stack, der in anderen Threads von CampSite erstellt wurde.

Angenommen, es gibt nur einen CampStove (ein einzelnes Objekt von CampStove, keine separaten Instanziierungen). Wenn ich nach einiger Vorstellung ein CampStove-Objekt teile, gibt es Überlegungen zum Multithreading. Ich möchte meinen Campingkocher nicht einschalten, verschwinden und dann wieder auftauchen, nachdem ein anderer Camper ihn ausgeschaltet hat – ich würde ewig prüfen, ob mein Hot Dog fertig ist, und das würde er nie tun. Sie müssten irgendwo etwas synchronisieren … in der CampStove-Klasse, in der Methode, die die CampSite aufrief, oder in der CampSite selbst … aber wie Duncan Jones sagt, “das ist eine andere Sache”.

Beachten Sie, dass selbst wenn wir in separaten Instantiierungen von campen würden nicht-statische CampSite-Objekte, die gemeinsame Nutzung eines campStove hätte die gleichen Multithreading-Überlegungen.

  • Das klingt gut für Date, ist aber für benutzerdefinierte Objekte nicht möglich, insbesondere wenn es sich um ein benutzerdefiniertes Objekt eines Drittanbieters handelt, das er nicht bearbeiten kann.

    – Saurabh Patil

    11. August 2017 um 10:36 Uhr

  • Wenn Sie im Falle eines Drittanbieters nicht klonen können, können Sie nicht viel tun, außer diesen Drittanbieter zu bitten, seine Klasseninstanzen Thread-sicher zu machen.

    – R. Kaja Mohideen

    9. Dezember 2018 um 8:00 Uhr

Benutzer-Avatar
SRK

Wir werden einige Beispiele nehmen, um zu sehen, ob die statische Methode Thread-Safe ist oder nicht.

Beispiel 1:

public static String concat (String st1, String str2) {
return str1 + str2
}

Die obige Methode ist jetzt Thread Safe.

Jetzt sehen wir ein weiteres Beispiel, das nicht Thread-sicher ist.

Beispiel 2:

 public static void concat(StringBuilder result, StringBuilder sb, StringBuilder sb1) {
    result.append(sb);
    result.append(sb1);
    }

Wenn Sie sehen, dass beide Methoden sehr, sehr primitiv sind, ist eine Thread-sicher und die andere nicht. Wieso den? Welchen Unterschied haben beide?

Sind statische Methoden in Dienstprogrammen anfällig für nicht Thread-sicher? Viele Fragen, oder?

Jetzt hängt alles davon ab, wie Sie die Methode implementieren und welche Art von Objekten Sie in Ihrer Methode verwenden. Verwenden Sie Thread-sichere Objekte? Sind diese Objekte/Klassen veränderbar?

Wenn Sie in Beispiel 1 sehen, dass die Argumente der concat-Methode vom Typ String sind, die unveränderlich sind und als Wert übergeben werden, ist diese Methode vollständig Thread-sicher.

In Beispiel 2 sind die Argumente nun vom Typ StringBuilder, die veränderbar sind, sodass andere Threads den Wert von StringBuilder ändern können, wodurch diese Methode möglicherweise nicht Thread-sicher ist.

Auch dies ist nicht ganz richtig. Wenn Sie diese Hilfsmethode mit lokalen Variablen aufrufen, haben Sie nie Probleme mit der Thread-Sicherheit. Da jeder Thread seine eigene Kopie für lokale Variablen verwendet, treten niemals Thread-Sicherheitsprobleme auf. Aber das geht über den Rahmen der obigen statischen Methode hinaus. Es hängt von der aufrufenden Funktion / dem aufrufenden Programm ab.

Jetzt sind statische Methoden in der Utility-Klasse eine Art normale Praxis. Wie können wir es also vermeiden? Wenn Sie Beispiel 2 sehen, ändere ich den 1. Parameter. Wenn Sie diese Methode wirklich Thread-sicher machen möchten, können Sie eine einfache Sache tun. Verwenden Sie entweder nicht veränderbare Variablen / Objekte oder ändern / modifizieren Sie keine Methodenparameter.

In Beispiel 2 haben wir bereits StringBuilder verwendet, der änderbar ist, sodass Sie die Implementierung ändern können, um die statische Methode wie folgt sicher zu machen:

public static String concat1(StringBuilder sb, StringBuilder sb1) {
StringBuilder result = new StringBuilder();
result.append(sb);
result.append(sb1);
return result.toString();
}

Gehen Sie noch einmal zu den Grundlagen. Denken Sie immer daran, wenn Sie unveränderliche Objekte und lokale Variablen verwenden, dann sind Sie meilenweit von Thread-Sicherheitsproblemen entfernt.

Aus dem Artikel (https://nikhilsidhaye.wordpress.com/2016/07/29/is-static-method-in-util-class-threadsafe/)Vielen Dank Nikhil Sidhaye für diesen einfachen Artikel

1242110cookie-checkWie kann die Fadensicherheit der Utility-Static-Methode gewährleistet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy