Java: Wie synchronisiert man Array-Zugriffe und welche Einschränkungen gibt es in einem synchronisierten Zustand?

8

Ich hatte ein 2x2 Array, auf dem zwei Threads arbeiteten.

ist es möglich, eine synchronisierte Anweisung in Java auf einem Array zu verwenden?

Wie funktioniert die Verriegelung? Der Java-Tutorial-Thread sagte, dass die synchronisierte Anweisung auf Objekten funktioniert, also war ich mir nicht sicher, was sie bedeuteten. Eine andere Seite sagte, dass ich eine Aussage wie

machen könnte %Vor%

Synchronisiert dies Zugriffe auf alles im Array, so dass das Array mit anderen Threads gesperrt ist?

Wenn ich ein zwei-d-Array habe, kann ich

verwenden

synchronized (array1[i]) , um eine der Zeilen des Arrays zu sperren?

und ist es möglich, einzelne Array-Werte zu sperren mit etwas wie

%Vor%

Aber ja, Tipps oder Hilfe werden sehr geschätzt. Eigentlich habe ich es schon richtig eingelesen. Aber ich möchte für zukünftige Verwendung wissen

    
James Street 08.09.2011, 16:01
quelle

4 Antworten

11

Ja, Sie können mit einem Array als Monitor-Objekt synchronisieren, da Arrays (selbst Arrays von Primitiven) Objekte in Java sind.

Sie können einen Codeblock auf einem bestimmten Monitor wie folgt synchronisieren:

%Vor%

Es empfiehlt sich, möglichst wenige Codezeilen zu synchronisieren.

Das Synchronisieren von Code auf einem Monitor hat keinerlei Auswirkungen auf den Monitor, sondern betrifft nur die Threads, die auf den synchronisierten Codeblock zugreifen. Bevor die Thread-Ausführung den Codeblock eingeben kann, muss sie die "Sperre" auf dem Monitor erhalten. Die Java-Laufzeitumgebung stellt sicher, dass höchstens ein Thread gleichzeitig die Sperre auf einem Monitor haben kann. Die Synchronisierung auf Ihrem Array verhindert nicht, dass unsynchronisierte Code-Blöcke darauf zugreifen! Der Trick besteht darin, sicherzustellen, dass alle Operationen, die nicht gleichzeitig ausgeführt werden sollen, innerhalb von auf dem Server synchronisierten Blöcken sind gleicher Monitor.

Da Java keine mehrdimensionalen Arrays, sondern nur Array-Arrays anbietet, können Sie mit Sicherheit auf einem verschachtelten Array synchronisieren, um eine feinere Synchronisation zu erreichen. Wenn Sie ein 2D-Array als Array von Zeilen modellieren, können Sie nur in Zeilen und nicht in Spalten synchronisieren, da die Spalten in diesem Beispiel nicht als separate Arrays dargestellt werden.

Sie können nur einzelne Array-Werte synchronisieren, wenn diese nicht primitiv sind, also Integer () anstelle von int. Beachten Sie, dass Integer () ein unveränderliches Objekt ist, sodass Sie seinen Wert nicht ändern können. Eine Lösung wäre, ein eigenes Cell () - Wrapper-Objekt mit einem Getter und Setter für den enthaltenen numerischen Wert zu erstellen. Auf diese Weise können Sie einem Thread erlauben, die Zelle zu sperren und dessen Wert sicher zu ändern.

Weil es mein freier Tag ist, habe ich beschlossen, Spaß zu haben und ein funktionierendes Beispiel für das geschaffen, was du beschreibst. Ja, das ist meine Idee, Spaß zu haben.

Klassen:

Die Anwendung startet mehrere Operationen auf derselben Matrix. Der einzige synchronisierte Codeblock befindet sich in der Klasse Operation. Wenn Sie die Synchronisierung entfernen, sind die Ergebnisse falsch, da zwei Operationen gleichzeitig dieselbe Zeile bearbeiten.

Ausgabe bei Synchronisation:

%Vor%

Beispielausgabe, wenn NICHT synchronisiert:

%Vor%

Beachten Sie, dass ich einige Thread.sleep () - Anweisungen in den Operationsimplementierungen hinzugefügt habe, um den Unterschied zwischen synchronisierter und unsynchronisierter Ausführung deutlicher zu machen.

    
Adriaan Koster 08.09.2011, 16:16
quelle
3

Das Schlüsselwort synchronized funktioniert nur mit Objekten.

Das Synchronisieren auf dem Array sperrt nur das Array (in Java ist ein Array ein Objekt).

Wenn Sie auf einem Array ein einzelnes Element synchronisieren, wobei Sie annehmen, dass es sich um Objekte und nicht um Primitive handelt, ist das eine andere Sperre. Sie können eins ohne das andere haben, und die Umkehrung ist auch wahr. Sie können nicht auf einem Primitiv synchronisieren.

Wenn Sie die gleichzeitige Änderung des Arrays verhindern müssen, synchronisieren Sie für einige Objekte im jeder Zugriff auf das Array. Sie können das gewünschte Objekt für diesen Zweck verwenden, aber es muss dasselbe sein, damit die Sache funktioniert. Beachten Sie Folgendes: Wenn Sie auf eine gemeinsam genutzte Ressource mit Synchronisierung und in anderen Teilen des Codes zugreifen, auf die Sie ohne Synchronisierung oder Synchronisierung mit einem anderen Objekt zugreifen, ist dies für nichts sinnvoll.

    
Mister Smith 08.09.2011 16:16
quelle
3

Nein, das Synchronisieren dieser Methode bedeutet nur, dass Sie das Array-Objekt sperren, nicht, dass Sie tatsächlich den Zugriff auf seine Methoden synchronisieren. Wenn Ihr Array für andere sichtbar ist, können sie dennoch auf den Inhalt zugreifen / ihn ändern, unabhängig davon, ob er gesperrt ist oder nicht. Nur sie können es nicht gleichzeitig sperren - wenn sie versuchen (von einem anderen Thread), werden sie blockiert, bis die Sperre von ihrem ursprünglichen Erwerber freigegeben wird.

Wenn Sie sicherstellen möchten, dass nur ein Thread gleichzeitig auf Ihr Array (oder ein Element davon) zugreift, müssen Sie es in eine Klasse einkapseln und alle öffentlichen Klassenmethoden, die das Array manipulieren, synchronisieren. (Sie können das Array zu diesem Zweck sperren, wenn Sie möchten - der einfachste und gebräuchlichste Ansatz besteht darin, die Methoden selbst als synchronized zu deklarieren. In diesem Fall wird ihr Inhalt auf this , dem einschließenden Objekt, synchronisiert) .

%Vor%     
Péter Török 08.09.2011 16:10
quelle
1

Wenn Sie ein Objekt oder Array synchronisieren, verhindern Sie, dass ein anderer Thread als dasselbe Objekt synchronisiert wird. Dies hindert Sie nicht daran, das Objekt zu verwenden, und keine andere Operation ist "gesperrt". Sie müssen sicherstellen, dass Sie das Objekt zuerst auf konsistente Weise gesperrt haben, damit es das Objekt "verriegelt".

    
Peter Lawrey 08.09.2011 16:55
quelle

Tags und Links