2012-05-14 6 views
12

Ich habe begonnen concurency und Threads in Java zu lernen. Ich kenne die Grundlagen von synchronisiert (d. H. Was es tut). Konzeptionell verstehe ich, dass es gegenseitigen exklusiven Zugriff auf eine freigegebene Ressource mit mehreren Threads in Java bietet. Aber wenn ich mit einem Beispiel wie unten konfrontiert bin, ist es eine gute Idee, es synchronisiert zu haben. Ich weiß, dass kritische Abschnitte des Codes synchronisiert werden sollten und dieses Schlüsselwort sollte nicht überstrapaziert werden oder es beeinflusst die Leistung.Synchronisation, Wann oder nicht?

public static synchronized List<AClass> sortA(AClass[] aArray) 
{ 
    List<AClass> aObj = getList(aArray); 

    Collections.sort(aObj, new AComparator()); 

    return aObj; 
} 

public static synchronized List<AClass> getList(AClass[] anArray) 
{ 
    //It converts an array to a list and returns 
} 
+2

benötigt, weil Ihre Methoden staatenlos zu sein scheinen. – Luca

Antwort

9

Angenommen, jeder Thread übergibt ein anderes Array dann ist keine Synchronisation erforderlich, da der Rest der Variablen lokal sind.

Wenn Sie stattdessen ein paar Fäden abfeuern alle sortA und vorbei einen Verweis auf das gleiche Array aufrufen, Sie in Schwierigkeiten ohne synchronized sein würde, weil sie mit einander stören würden.

Vorsicht, dass es aus dem Beispiel scheinen würde, dass die getList Methode ein neues List aus einem Array zurückgibt, so dass selbst dann, wenn die Fäden die gleiche Array übergeben, können Sie verschiedene List Objekte zu bekommen. Das ist irreführend. Beispielsweise erstellt Arrays.asList mit einem List durch das angegebene Array gesichert, aber die javadoc eindeutig fest, dass Changes to the returned list "write through" to the array. so vorsichtig sein, diese über.

2

Ihre statischen Methoden hängen nicht von einem gemeinsam genutzten Status ab und müssen daher nicht synchronisiert werden.

2

Es gibt keine Regel, die definiert ist, wann synchronisiert werden soll. Wenn Sie nicht sicher sind, dass auf Ihren Code nicht durch gleichzeitige Threads zugegriffen wird, können Sie die Verwendung von synchronized vermeiden.

2

Synchronisieren, wie Sie es richtig dargestellt haben, hat Auswirkungen auf den Durchsatz Ihrer Anwendung und kann auch zu verhungernden Threads führen.

Alle bekommen grundsätzlich nicht blockierende sein sollte als Sammlungen unter Gleichzeitigkeit Paket implementiert haben.

Wie in Ihrem Beispiel übergeben alle aufrufenden Thread dort eigene Kopie des Arrays, getList muss nicht synchronisiert werden, so ist sortA Methode wie alle anderen Variablen lokal sind.

Lokale Variablen leben auf Stapel und jeder Thread hat seinen eigenen Stapel, so dass andere Threads ihn nicht stören können.

Sie benötigen eine Synchronisierung, wenn Sie den Status des Objekts ändern, das andere Threads in einem konsistenten Zustand sehen sollten, wenn Ihre Aufrufe den Status des Objekts nicht ändern, das Sie nicht synchronisieren müssen.

3

Die Synchronisierung wird normalerweise benötigt, wenn Sie Daten zwischen mehreren Aufrufen teilen und die Daten möglicherweise geändert werden, was zu Inkonsistenzen führen kann. Wenn die Daten schreibgeschützt sind, müssen Sie nicht synchronisieren.

In dem obigen Codefragment, gibt es keine Daten, die gemeinsam genutzt wird. Die Methoden arbeiten mit der angegebenen Eingabe und geben die Ausgabe zurück. Wenn mehrere Threads eine Ihrer Methoden aufrufen, hat jeder Aufruf seine eigene Eingabe und Ausgabe. Daher gibt es keine Möglichkeit der Inkonsistenz. Daher müssen Ihre Methoden im obigen Snippet nicht synchronisiert werden.

Synchronisation, wenn sie unnötigerweise verwendet wird, würde die Leistung aufgrund der involvierten Gemeinkosten sicher verschlechtern und sollte deshalb vorsichtig nur bei Bedarf verwendet werden.

+0

Woher wissen Sie, dass keine Daten freigegeben werden? Die Threads können dasselbe Array an die 'sortA'-Methode übergeben. – Tudor

+1

Eine ziemliche Möglichkeit! Nun, in diesem Fall müssten Sie sicher synchronisieren. Der Punkt ist, dass die Benutzer des Codes wissen sollten, ob Ihr Code Thread-sicher ist oder nicht. Als Entwickler wissen Sie, ob Ihr Code Thread-sicher sein soll oder nicht. Wenn nicht, müssen Sie es für die Benutzer dokumentieren, damit sie in interessanten Szenarien explizit synchronisieren können. Sie müssen nicht alles in Ihrem Code synchronisieren. – Drona

+1

Das Synchronisieren einer statischen Methode im oben genannten Snippet für die von ihr bereitgestellten Funktionen ist nicht korrekt. Die Benutzer sollten sich vor dem von Ihnen genannten Szenario schützen, wo immer dies erforderlich ist. – Drona

2

Ich würde nicht synchronized auf Single-Thread-Code verwenden. d. h. wo keine Möglichkeit besteht, auf ein Objekt durch mehrere Threads zuzugreifen.

Das mag selbstverständlich erscheinen, aber ~ 99% des String im JDK verwendet wird, kann nur von einem Thread verwendet werden kann, mit einem String ersetzt wird keine Synchronisation (die nicht synchronisiert ist)