2013-03-02 3 views
6

Java-Code:Ist der folgende Inkrementierungscode-Thread in Java sicher?

public class IncreaseTest { 
    public static int value = 0; 

    public synchronized int increment() { 
     return value++; 
    } 
} 

Ist Methode increment() Thread-sicher? Muss ich den Modifikator Stichwort volatile hinzufügen wie folgt:

public static volatile int value = 0; 
+0

Sie sollten die Sprache angeben. – paxdiablo

+0

Vielen Dank für Ihre Erinnerung – codeisee

Antwort

18

Dieser Code ist nicht threadsicher. Die Instanzmethode wird auf einer Instanz synchronisiert, wenn Sie mehrere Instanzen haben, werden sie nicht den gleichen Monitor verwenden, und daher können die Aktualisierungen verschachtelt werden.

Sie müssen entweder die statische aus dem value Feld entfernen oder statisch zur increment() Methode hinzufügen.

Auch, wie Sie value public gemacht haben, gibt es das zusätzliche Problem, dass Wert außerhalb dieser Methode geändert oder gelesen werden kann, ohne Synchronisierung zu verwenden, die zum Lesen alter Werte führen könnte.

Code So ändert den folgenden wird es machen Thread-sicher-:

public class IncreaseTest { 
    private int value = 0; 

    public synchronized int increment() { 
     return value++; 
    } 
} 
+0

(+1) Guter Punkt. Ich habe das 'Static' komplett übersehen. – NPE

+0

@ NPE Also habe ich anfangs. –

+0

privater int-Wert = 0; // wenn static entfernen und public in private ändern, ist das Thread sicher? – codeisee

0

Wenn Sie diese Methode in zwei Threads verwenden, dann müssen Sie das Schlüsselwort volatile. Ohne es wird ein anderer Thread möglicherweise nicht den aktuellsten Wert erhalten. (C#)

+0

Das synchronisierte Schlüsselwort in der Methodendeklaration ist das gleiche wie ein 'lock (this) {...}' in C#. –

1

Ich glaube nicht, dieser Thread sicher ist, da die statische Variable ist öffentlich und kann von anderen Threads in einem nicht zugegriffen werden fadensichere Art und Weise. Um sicher zu fädeln müssen Sie die Variable wie folgt deklarieren:

public static volatile int value; 

Jetzt value flüchtig ist, wird in einem synchronisierten Block zugegriffen werden.

+0

Die Variable flüchtig zu machen ist anders als der Zugriff von einem synchronisierten Block. Die Operation ++ ist immer noch keine atomare Operation, selbst wenn die Variable flüchtig ist. –

+0

"Zugriff auf die Variable verhält sich so, als wäre sie in einem synchronisierten Block eingeschlossen, der auf sich selbst synchronisiert ist." nach [dieser] (http://www.javamex.com/tutorials/synchronization_volatile.shtml) – niculare

+3

Der Vergleich in dem Artikel ist ein schlechter, fehleranfälliger.Insbesondere macht "value ++" zwei verschiedene Zugriffe auf value: einen, um den Wert zu lesen, und einen anderen, um ihn zu schreiben. Wenn volume "value" gemacht wird, wird nicht sichergestellt, dass das Lesen und das Schreiben in einer einzigen atomaren Operation eingeschlossen sind. Nur die Synchronisation sorgt dafür. Das bedeutet, dass Sie zwei Threads parallel lesen und dann parallel schreiben können, und der Wert würde um 1 erhöht statt um 2 inkrementiert werden. –

0

Sie sollten wahrscheinlich verwenden atomicvars

+0

Atomare Vars sind kein Problem für Threading-Probleme per se. IMHO ist es besser zu verstehen, was unter der Haube vor sich geht. –