Ist es sicher, Objekte zu manipulieren, dass ich vor meinem Thread erstellt, wenn ich nicht explizit auf dem Thread zugreifen, die sie erstellt?

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

Frage

Ich arbeite an einer Kakao-Software, und um die GUI ansprechbar während eines massiven Datenimports (Core Data) zu halten Ich brauche den Import außerhalb des Haupt-Thread ausgeführt werden.

Ist es sicher, diese Objekte auch zugreifen, wenn ich sie in dem Haupt-Thread erstellt, ohne Schlösser mit , wenn Ich greife nicht explizit diese Objekte während der Thread ausgeführt wird.

War es hilfreich?

Lösung

Mit Core Data, sollten Sie einen separaten verwaltete Objektkontext für Ihren Import Thread zu verwenden, die mit dem gleichen Koordinator und persistenten Speichern. Sie können nicht einfach Objekte in einem von der Haupt-Thread in einem anderen Thread verwendet Kontext geschaffen werfen und erwarten, dass sie arbeiten. Darüber hinaus können Sie Ihre eigene Verriegelung für das nicht tun; Sie müssen sich das verwaltete Objektkontext sind die Objekte in, gegebenenfalls mindestens sperren. Aber wenn diese Objekte durch Ihre Ansichten, die eine Steuerelemente gebunden sind, gibt es keinen „Haken“, dass Sie diese Verriegelung des Kontextes hinzufügen können.

Es gibt kein freies Mittagessen.

Ben Trumbull erklärt einige der Gründe, warum Sie einen separaten Kontext verwenden müssen, und warum „nur lesen“ ist nicht so einfach oder so sicher wie Sie vielleicht denken, in dieser große Beitrag von Ende 2004 auf der WebObjects-dev Liste . (Der ganze Thread ist groß.) Er ist die Enterprise Objects Framework Diskussion und WebObjects, aber sein Rat ist, in vollem Umfang anwendbar als auch auf Core Data. Ersetzen Sie einfach "EC" mit "NSManagedObjectContext" und "EOF" mit "Core Data" in dem Fleisch seiner Botschaft.

Die Lösung für das Problem der gemeinsamen Nutzung von Daten zwischen Threads in Kerndaten, wie die Enterprise Objects Framework, bevor es wird „dies nicht tun.“ Wenn Sie weiter darüber nachgedacht haben und Sie wirklich, ehrlich müssen Daten zwischen Threads teilen, dann ist die Lösung unabhängig Objektgraphen in faden isoliert Kontexten zu halten, und verwenden Sie die Informationen in der speichern Benachrichtigung von einem Kontext der sagen, anderer Zusammenhang, was erneut zu holen. -[NSManagedObjectContext refreshObject:mergeChanges:] ist speziell auf diese Anwendung unterstützen

Andere Tipps

Ich glaube, dass diese nicht sicher mit NSManagedObjects (oder Unterklassen) zu tun, die von einem Coredata NSManagedObjectContext verwaltet werden. Im Allgemeinen kann Coredata viele schwierigen Dinge mit dem Zustand von gemanagten Objekten tun, einschließlich Brennen auf diese Objekte in separaten Threads hervorgerufene Fehler. Insbesondere [NSManagedObject initWithEntity:insertIntoManagedObjectContext:] (der designierte Initialisierer für NSManagedObjects ab OS X 10.5), garantiert nicht, dass das zurückgegebene Objekt ist sicher zu einem anderen Thread zu übergeben.

Mit Coredata mit mehreren Threads ist gut dokumentiert auf Apples dev Website .

Die ganzen Punktschlösser zu verwenden, sind, um sicherzustellen, dass zwei Threads versuchen, nicht die gleiche Ressource zugreifen. Wenn Sie, dass durch einen anderen Mechanismus garantieren kann, gehen für sie.

Auch wenn es sicher ist, aber es ist nicht die beste Praxis gemeinsam genutzter Daten zwischen Threads zu verwenden, ohne den Zugang zu diesen Bereichen zu synchronisieren. Es spielt keine Rolle, welchen Thread das Objekt erstellt hat, aber wenn mehr als eine Zeile der Ausführung (Thread / Prozesses) wird das Objekt in der gleichen Zeit zugreifen, da es zu Dateninkonsistenz führen kann.

Wenn Sie absolut sicher sind, dass nur ein Thread jemals dieses Objekt zugreifen, als es sicher sein würde, um nicht den Zugang zu synchronisieren. Selbst dann würde ich lieber jetzt meinem Code setzen Synchronisation als bis später warten, wenn eine Änderung in der Anwendung ein zweites Gewinde setzt etwa die gleichen Daten ohne Bedenken teilt Zugang zu synchronisieren.

Ja, es ist sicher. Ein ziemlich übliches Muster ist ein Objekt zu erstellen, es dann zu einer Warteschlange oder eine anderen Sammlung. Ein zweiter „Verbraucher“ Thread nimmt Elemente aus der Warteschlange und macht etwas mit ihnen. Hier würden Sie brauchen, um die Warteschlange zu synchronisieren, aber nicht die Objekte, die in die Warteschlange aufgenommen werden.

Es ist keine gute Idee, einfach alles und das Beste hoffen zu synchronisieren. Sie werden sehr sorgfältig über Ihr Design nachdenken müssen und genau, welche Themen auf Ihre Objekte wirken können.

Zwei Dinge zu beachten sind:

  • Sie müssen in der Lage sein, zu garantieren, dass das Objekt vollständig erstellt und initialisiert, bevor sie zu anderen Threads zur Verfügung gestellt wird.
  • Es muß einen Mechanismus geben, durch die die Haupt (GUI) Thread detektiert, daß die Daten geladen wurde, und alles ist gut. sein, um Thread-sicher wird dies unweigerlich Verriegelung irgendeine Art verbunden.

Ja, Sie können es tun, wird es sicher sein

... bis der zweite Programmierer kommt herum und verstehen nicht die gleichen Annahmen, die Sie gemacht haben. Der zweiten (oder 3., 4., 5., ...) Programmierer ist wahrscheinlich das Objekt in einem nicht sicheren Weg (in dem Schöpfer Thread) zu beginnen. Die verursachten Probleme könnten sehr subtil und schwierig sein, nach unten zu verfolgen. Allein aus diesem Grunde, und weil es so verlockend diese Aufgabe in mehreren Threads zu verwenden, würde ich das Objekt Thread-sicher machen.

Um zu klären, (dank denen, die Kommentare hinterlassen):

Mit dem „thread-safe“ Ich meine Ausarbeitung programmatisch ein Schema Threading Probleme zu vermeiden. Ich bin nicht unbedingt bedeuten, ein Sperrschema um Ihr Objekt zu entwickeln. Sie könnten eine Art und Weise in Ihrer Sprache finden, um es illegal zu machen (oder sehr hart) das Objekt in dem Schöpfer Thread zu verwenden. Zum Beispiel Einschränkung des Umfangs, in dem creator Gewinde, auf den Block von Code, der das Objekt erzeugt. Einmal erstellt, übergeben Sie das Objekt über den Benutzer-Thread, um sicherzustellen, dass der Schöpfer-Thread nicht mehr einen Verweis auf sie hat.

Zum Beispiel in C ++

void CreateObject()
{
    Object* sharedObj = new Object();
    PassObjectToUsingThread( sharedObj); // this function would be system dependent
}

Dann in Ihrem Schaffen Thread, die Sie nicht mehr Zugriff auf das Objekt nach seiner Gründung wird Verantwortung für die Verwendung von Thread übergeben.

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