In einem Multithreaded (Java oder .NET) Programm, kann ich davon ausgehen, dass eine Variable Kopieren Atom ist?

StackOverflow https://stackoverflow.com/questions/473111

Frage

Ich war sich Gedanken über Rennbedingungen in einer Anwendung Ich bin der Gestaltung, wenn ich über diese Frage habe mich gefragt.

Lassen Sie uns sagen, dass ich ein großes Array oder einer Sammlung von einer Art, die von einer Komponente meines Programms verwaltet wird, wollen wir, dass die Komponente-Monitor aufrufen. Seine Aufgabe ist es, regelmäßig zu überprüfen, ob die Sammlung „dirty“ ist, d. e. hat vor kurzem geändert, und wenn ja, einen Schnappschuss auf die Festplatte schreiben (dies ist die Anwendung im Falle eines Absturzes Checkpoint) und markieren Sie ihn als sauber wieder.

Weitere Komponenten des gleichen Programms, in einem anderen Thread ausgeführt wird, die Methoden des Monitors aufrufen, um Daten hinzufügen oder ändern Daten im Array / Sammlung. Diese Verfahren markieren die Sammlung als schmutzig.

Nun laufen die Änderungsverfahren in den anderen Komponenten Fäden, nicht wahr? Und wenn ich nicht so glücklich bin, könnten sie genannt werden, während der Schnappschuss auf die Festplatte geschrieben werden, Änderungsdaten, die bereits geschrieben wurde, stellen Sie die Dirty-Flag und das Gewinde des Monitors führt zum Löschen es nur danach, ohne die Änderungen (sie gespeichert haben das Element war schon vorbei, wenn es geändert). Also ich habe eine schmutzige Sammlung, die als sauber markiert ist.

Für eine Weile dachte ich, dass ich vielleicht das Problem, indem sie eine temporäre Kopie der Sammlung lösen könnte, markieren Sie es sauber und dann gehen und die Kopie serialisiert. Aber wäre das Kopieren atomar, i. e. kann ich sicher sein, dass die Sammlung nicht ändern wird, während ich es Kopieren bin?

Inzwischen, ich glaube, ich habe bessere Lösungen gefunden, wie

  • Setzen einen Lockflag vor dem Schreiben auf der Platte beginnen und die Daten zu verändern Methoden machen warten, bis das Flag nicht gesetzt
  • haben, schreiben die Datenänderungsverfahren zu einem „change-Warteschlange“ statt direkt auf die Sammlung und haben den Thread, der den Plattenschreibvorgang nicht, die
  • Warteschlange

, und ich denke, die Lockflag könnte der beste Weg zu gehen. Aber ich bin immer noch neugierig: Ist das Kopieren eine Variable Atom

?

Follow-up : Vielleicht in einer Frage der eigenen gehen sollte, aber es ist eigentlich sehr ähnlich. Nach den Antworten unten, könnte mein „Lock-Flag“ -Ansatz auch nicht arbeiten, nicht wahr? Da die Datenänderungsverfahren könnten den Sperr-Flag überprüfen, während es auf den „gesperrten“ Wert gesetzt wird und entscheiden, es ist nicht gesperrt. Also brauche ich eine spezielle Konstruktion wie ein Mutex, wenn ich wirklich das richtig machen will, nicht wahr?


Ein großes Lob an erickson für seine sehr hilfreiche Antwort auf meinem Follow-up. Ich wirklich haben sollte diese zwei Fragen gestellt, so konnte ich zwei Antworten angenommen haben. Bitte stimmen ihn auch.

War es hilfreich?

Lösung

Nein. Zum Beispiel sind lange Variablen in Java nicht atomar auf 32-Bit-Maschinen.

Darüber hinaus gibt es ein „Thread-Caching“ Problem - es sei denn, Ihre Variable volatile oder innerhalb synchronisierten Block ist, kann ein anderer Thread die Änderung nicht auf Variablenwert sehen. Dies gilt für alle Arten von Variablen, nicht nur lang.

Lesen Sie hier: http://gee.cs.oswego.edu/dl /cpj/jmm.html , vor allem "Unteilbarkeit" und "Sichtbarkeit" Absätze.

Andere Tipps

Nein, es ist nicht atomar. Sehen Sie diese Frage warum und was zu tun ist.

Werfen Sie einen Blick auf java.util.concurrent.atomic -. es kann einige gute Dinge in dort können Sie

Sie müssen über die Sichtbarkeit von Änderungen an anderen Threads betroffen sein, wenn auf der JVM arbeiten. In der Regel sollten Sie Ihre Aufgaben innerhalb eines synchronized Block machen, oder die Variable volatile werden sollte, oder sollten Sie eine Variable Wrapper aus dem java.util.concurrent.atomic Paket verwenden.

Doch in Ihrem Fall, es klingt wie Sie nur einen Thread haben, der jemals den „schmutzigen“ Flag-den Faden löscht, die die Daten weiterhin bestehen. Wenn das der Fall ist, deaktivieren Sie das Flag vor , um die Daten zu schreiben. Wenn andere Threads es gesetzt , während Sie die Daten schreiben, wird bleiben sie bis zum nächsten geplanten Schreib eingestellt. Ich würde eine AtomicBoolean verwenden, Ihre Ausdauer Thread Unteilbarkeit zwischen Überprüfung der Flagge zu geben und Clearing es, wie folgt aus:

private final AtomicBoolean dirty = new AtomicBoolean();

/**
 * Any method that modifies the data structure should set the dirty flag.
 */
public void modify() {
  /* Modify the data first. */
  ...
  /* Set the flag afterward. */
  dirty.set(true);
}

private class Persister extends Thread {
  public void run() {
    while (!Thread.interrupted()) {
      if (dirty.getAndSet(false)) {
        /* The dirty flag was set; this thread cleared it 
         * and should now persist the data. */
         ...
      }
    }
  }
}

ein 32-Bit-Einstellung (zumindest in .NET) ist atomar, aber es tut dir nicht gut. Sie haben es zu lesen zu wissen, ob es gesperrt ist, so dass Sie sie lesen könnten, und nach dem Lesen, jemand anderes liest es, bevor Sie es einstellen können, so zwei Threads am Ende innen , um den „geschützten“ Code . Dies ist genau das, was tatsächlich Synchronisationsobjekte (wie .NET Monitor-Klasse) sind für. Sie könnten eine verriegelte verwenden zu überprüfen und die Sperrvariable zu erhöhen als auch.

Siehe auch: ist eine Variable in C # Zugriff auf eine Atom Betrieb?

hängt sehr stark von der Hardware und JVM Sie ausführen

Auf einiger Hardware und einige JVMs einige Kopien atomar sein aber es ist sicherer, diese anzunehmen, ist nicht der Fall, selbst eine einfache Integer-Zuordnung auf ganzzahlige kann bis zu vier Maschinenbefehle auf x856 Hardware übersetzen.

String und Array-Kopien können eine Folge von Tausenden von Anweisungen beinhalten und es ist möglich, dass zwei Threads simultan zu aktualisieren.

Wie ich es verstehe, nicht immer.

Int32 sein wird, wird ein Int64 sein nicht auf einem 32-Bit-Sytem wie benötigt es 2 x 32 Bit. Daher ist es nicht in einem 32-Bit-Zelle passen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top