it-swarm.com.de

Atomoperationen und Multithreading

Vor kurzem las ich ein Tutorial, in dem ich auf eine Aussage gestoßen bin, die besagt, dass ..

"Die Java-Sprachspezifikation garantiert, dass das Lesen oder Schreiben einer Variablen eine atomare Operation ist (es sei denn, die Variable ist vom Typ long oder double). Operationsvariablen des Typs long oder double sind nur atomar, wenn sie mit dem Schlüsselwort volatile deklariert werden."

AtomicInteger oder AtomicLong bietet Methoden wie getAndDecrement(), getAndIncrement() und getAndSet(), die atomar sind.

Ich wurde ein wenig mit der obigen Anweisung verwirrt. Bitte klären Sie wann SieAtomicInteger- oder AtomicLong-Klassen verwenden.

27
MaheshVarma

a = 28 (wobei a eine int ist) ist eine atomare Operation. a++ ist jedoch keine atomare Operation, da der Wert von a, eine Inkrementierung und ein Ergebnis des Ergebnisses gelesen werden müssen. Wenn Sie mit a++ einen Thread-sicheren Zähler implementieren, könnten Sie den Wert gleichzeitig von zwei Threads lesen (z. B. 26) und dann sowohl inkrementieren als auch gleichzeitig schreiben, was als Ergebnis 27 ergibt 28.

AtomicInteger löst dieses Problem, indem Sie atomare Operationen wie die von Ihnen aufgelisteten bereitstellen. In meinem Beispiel würden Sie beispielsweise incrementAndGet() verwenden, wodurch der Endwert 28 und nicht 27 lautet.

48
JB Nizet

Atomisch bedeutet, dass die Operation abgeschlossen wird, ohne dass etwas dazwischen passiert. z.B. getAndDecrement () in AtomicInteger garantiert, dass die Variable zur selben Zeit zurückgegeben und dekrementiert wird. 

Wenn es sich nicht um eine atomare Operation handelt, besteht die Möglichkeit, dass der Wert dekrementiert wird (z. B. von 3 auf 2), dann von einem anderen Thread geändert (z. B. von 2 auf 5 geändert) und dann als 5 zurückgegeben wird.

8
Ren

Sie benötigen eine AtomicInteger, wenn Sie eine Variable lesen und ein Ergebnis schreiben müssen, abhängig vom gelesenen Wert. Beispielsweise liest i++i (z. B. 3) und schreibt i+1 (z. B. 4). Ein Thread kann in der Zwischenzeit unterbrochen werden, und drei andere Threads erhöhen ebenfalls i. Nun, da wir zurückkommen, hat i tatsächlich den Wert 6, aber unser Thread schreibt noch 4, basierend auf dem, was er zuvor gelesen hat.

AtomicInteger.getAndIncrement stellt sicher, dass Sie nicht unterbrochen sind und daher immer korrekt inkrementieren. Außerdem wird das Ergebnis immer in den Speicher geschrieben, während ein nichtflüchtiger i möglicherweise nicht in den Speicher geschrieben wird. In diesem Fall können andere Threads die Änderungen nicht einmal sehen.

3
Matthias Meid

Ich denke, das bedeutet, dass lange und doppelte Lesevorgänge atomar und Schreiboperationen atomar sind. Aber Lesen + Schreiben ist nicht atomar.

volatile long num;
num = num+1

Das oben genannte ist nicht threadsicher. Lesen und Schreiben sind zwei getrennte Operationen. Es ist garantiert, dass jeder von ihnen atomar ist, der Ausdruck jedoch nicht.

Um den Thread sicherer zu machen, müssten Sie AtomicLong verwenden und die getAndIncrement-Funktion verwenden.

0
gkamal

Sie verwenden int oder long, basierend auf der oberen/unteren Grenze des Nummernbereichs, mit dem Sie sich befassen. Bitte mischen Sie kein nicht-atomares Verhalten von long mit AtomicLong. Was auch immer Sie oben geschrieben haben, ist richtig, aber Sie mischen wahrscheinlich beide Konzepte. AtomicXXX ist in Fällen nützlich, in denen Sie Operationen des Typs "Compare & Set" ausführen. Selbst wenn zum Beispiel int atomar geändert/gelesen werden kann, ist folgender Code in einer Multithread-Umgebung falsch:

int i =10
..
..
..
if(i == 10) i++;

in einer Multithread-Umgebung können zwei Threads auf diesen Code atomar und auf den aktualisierten Wert von i zugreifen und ihn in einen konsistenten Zustand versetzen. SO befassen sich mit solchen Situationen normalerweise, Sie schützen den Code "if (i == 10) i ++;" mit synchronisiertem Block. Die AtomicInteger-Klasse bietet jedoch die API, um dies zu erreichen, ohne synchronisierte Blöcke zu verwenden, die langsamer sind. Gleiches gilt für AtmoicLong-APIs

0
Saurabh

die Atomizität einer Operation ist erforderlich, wenn Sie eine Variable mutieren. int a = 10; zu tun ist eine atomare Operation, aber nicht die, die das Problem verursacht. Die problemgebenden Operationen sind normalerweise mutierende Operationen wie a++ oder a = a + 2; und so weiter.

Die Java-Spezifikation garantiert, dass 'Lesen' und 'Schreiben' atomare Operationen sind und nicht deren Kombinationen. Eine Operation, die liest, addiert 1 und schreibt das Ergebnis zurück, ist laut Spezifikation nicht atomar. Solche Vorgänge werden als zusammengesetzte Vorgänge bezeichnet und müssen im Zusammenhang mit ihrer Verwendung in unserem Code normalerweise atomar sein.

Atomtypen helfen, dieses Problem zu lösen. Die Verwendung von incrementAndget () für einen atomaren Typ führt 'reads aus, addiert 1 und schreibt das Ergebnis zurück und liest das neue Ergebnis' eine einzelne atomare Operation im Kontext der Thread-Sicherheit.

Hoffe das hilft. Übrigens sollten Sie diesen Artikel ( http://walivi.wordpress.com/2013/08/24/concurrency-in-Java-a-beginner-introduction/ ) über die Grundlagen von Parallelität und Threads lesen. es erklärt solches Zeug wunderschön.

0
Nazgul