È sicuro manipolare oggetti che ho creato all'esterno del mio thread se non accedo esplicitamente ad essi nel thread che li ha creati?

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

Domanda

Sto lavorando su un software Cocoa e per mantenere la GUI reattiva durante un'importazione massiccia di dati (Core Data) devo eseguire l'importazione al di fuori del thread principale.

È sicuro accedere a tali oggetti anche se li ho creati nel thread principale senza utilizzare i blocchi Se Non accedo esplicitamente a tali oggetti mentre il thread è in esecuzione.

È stato utile?

Soluzione

Con Core Data, dovresti avere un contesto di oggetto gestito separato da utilizzare per il thread di importazione, connesso allo stesso coordinatore e archivio permanente.Non puoi semplicemente lanciare oggetti creati in un contesto utilizzato dal thread principale in un altro thread e aspettarti che funzionino.Inoltre, non puoi eseguire il tuo blocco per questo;è necessario bloccare almeno il contesto dell'oggetto gestito in cui si trovano gli oggetti, come appropriato.Ma se quegli oggetti sono vincolati dalle tue visualizzazioni e controlli, non ci sono "ganci" a cui puoi aggiungere quel blocco del contesto.

Non c'è pranzo gratis.

Ben Trumbull spiega alcuni dei motivi per cui è necessario utilizzare un contesto separato e perché "semplicemente leggere" non è così semplice o sicuro come si potrebbe pensare, in questo fantastico post della fine del 2004 nell'elenco webobjects-dev.(L'intero thread è fantastico.) Sta discutendo di Enterprise Objects Framework e WebObjects, ma il suo consiglio è pienamente applicabile anche a Core Data.Basta sostituire "EC" con "NSManagedObjectContext" e "EOF" con "Core Data" nella parte centrale del suo messaggio.

La soluzione al problema della condivisione dei dati tra i thread nei dati principali, come il framework degli oggetti aziendali prima di esso, è "no". Se ci hai pensato ulteriormente e davvero, onestamente devi condividere i dati tra i thread, allora la soluzione è mantenere i grafici di oggetti indipendenti in contesti isolati da thread e utilizzare le informazioni nella notifica di salvataggio da un contesto per raccontare il Altro contesto cosa rimborsare. -[NSManagedObjectContext refreshObject:mergeChanges:] è specificamente progettato per supportare questo utilizzo.

Altri suggerimenti

Credo che sia così non sicuro a che fare con NSManagedObjects (o sottoclassi) gestiti da un CoreData NSManagedObjectContext.In generale, CoreData può fare molte cose complicate con lo stato degli oggetti gestiti, inclusa l'attivazione di errori relativi a tali oggetti in thread separati.In particolare, [NSManagedObject initWithEntity:insertIntoManagedObjectContext:] (l'inizializzatore designato per NSManagedObjects a partire da OS X 10.5), non garantisce che l'oggetto restituito possa essere passato in sicurezza a un altro thread.

L'uso di CoreData con più thread è ben documentato su Apple sito di sviluppo.

Lo scopo principale dell'utilizzo dei blocchi è garantire che due thread non tentino di accedere alla stessa risorsa.Se puoi garantirlo attraverso qualche altro meccanismo, fallo.

Anche se è sicuro, non è la pratica migliore utilizzare dati condivisi tra thread senza sincronizzare l'accesso a tali campi.Non importa quale thread ha creato l'oggetto, ma se più di una riga di esecuzione (thread/processo) accede all'oggetto contemporaneamente, poiché ciò può portare a un'incoerenza dei dati.

Se sei assolutamente sicuro che solo un thread accederà a questo oggetto, sarebbe sicuro non sincronizzare l'accesso.Anche in questo caso, preferirei inserire la sincronizzazione nel mio codice adesso piuttosto che aspettare più tardi, quando una modifica nell'applicazione inserirà un secondo thread che condivide gli stessi dati senza preoccuparsi della sincronizzazione dell'accesso.

Sì, è sicuro.Uno schema piuttosto comune consiste nel creare un oggetto, quindi aggiungerlo a una coda o ad un'altra raccolta.Un secondo thread "consumatore" prende gli elementi dalla coda e fa qualcosa con essi.In questo caso, dovresti sincronizzare la coda ma non gli oggetti aggiunti alla coda.

NON è una buona idea semplicemente sincronizzare tutto e sperare per il meglio.Dovrai pensare molto attentamente al tuo design e esattamente quali fili possono agire sui tuoi oggetti.

Due cose da considerare sono:

  • Devi essere in grado di garantire che l'oggetto sia completamente creato e inizializzato prima che venga reso disponibile ad altri thread.
  • Deve esserci un meccanismo mediante il quale il thread principale (GUI) rileva che i dati sono stati caricati e che tutto va bene.Per essere sicuri, ciò comporterà inevitabilmente un blocco di qualche tipo.

Sì, puoi farlo, sarà sicuro

...finché non arriva il secondo programmatore e non capisce le stesse ipotesi che hai fatto.È probabile che il secondo programmatore (o 3°, 4°, 5°, ...) inizi a utilizzare l'oggetto in modo non sicuro (nel thread del creatore).I problemi causati potrebbero essere molto subdoli e difficili da rintracciare.Solo per questo motivo, e poiché è così allettante utilizzare questo oggetto in più thread, renderei sicuro il thread dell'oggetto.

Per fare chiarezza, (grazie a chi ha lasciato commenti):

Per "thread-safe" intendo l'ideazione programmatica di uno schema per evitare problemi di threading.Non intendo necessariamente ideare uno schema di blocco attorno al tuo oggetto.Potresti trovare un modo nella tua lingua per rendere illegale (o molto difficile) l'uso dell'oggetto nel thread del creatore.Ad esempio, limitando l'ambito, nel thread creatore, al blocco di codice che crea l'oggetto.Una volta creato, passa l'oggetto al thread utente, assicurandoti che il thread creatore non abbia più riferimenti ad esso.

Ad esempio, in C++

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

Quindi nel thread di creazione, non hai più accesso all'oggetto dopo la sua creazione, la responsabilità viene passata al thread che lo utilizza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top