2015-04-25 12 views
5

L'immagine di Visual Studio "blocca altri thread". C'è una versione alternativa _fread_nolock, che legge "senza bloccare altri thread", che dovrebbe essere usata solo "in contesti thread-safe come applicazioni a thread singolo o dove l'ambito chiamante già gestisce l'isolamento del thread."Quale livello si blocca? A che livello devono essere attivi?

Anche dopo aver letto altre discussioni piuttosto rilevanti sui due, sono confuso se il blocco fread implementa su una specifica struttura FILE, un file specifico specifico, o su tutte le chiamate su file completamente diversi.

Se si utilizzano le versioni nolock, quale livello di blocco è necessario fornire? Più thread in parallelo possono leggere file separati senza alcun blocco? Più thread in parallelo possono scrivere file separati senza alcun blocco? O ci sono variabili globali o statiche coinvolte che potrebbero essere danneggiate?

Quindi, utilizzando le versioni nolock, è possibile ottenere un throughput I/O migliore (se non si stanno muovendo inutilmente teste, come leggere unità separate o un'unità SSD), o è il potenziale guadagno basta ridurre le serrature ridondanti a un unico blocco (che dovrebbe essere trascurabile).

La funzione di ifstream.read funziona come quella normale? (Non vedo una versione nolock di esso.)

+0

La libreria di runtime C risale a un tempo lungo, molto prima che i sistemi operativi supportassero i thread. La specifica non è mai stata aggiornata per dire cosa * dovrebbe * accadere quando due thread chiamano fread() sullo stesso file. Quindi gli scrittori di librerie dovevano arrangiarsi da soli per far funzionare le vecchie specifiche. Non è come se il CRT fornisse ai programmatori un altro modo. Le probabilità che tu sia * effettivamente * avanti cercando di aggirare il blocco è molto bassa, l'I/O è piuttosto lento. Tuttavia, ciò non è vero in tutti i casi, ad esempio le locali sono estremamente costose. Il destino della maggior parte dei programmi che cerca di farlo bene è quello di evitare il CRT. –

risposta

3

L'implementazione della libreria standard MS supporta pienamente il multi-threading. La serie C++ spiegare questa determinazione:

27.2.3: accesso simultaneo a un oggetto flusso, oggetto buffer di flusso, o flusso C Library di più thread può causare un data gara se non diversamente specificato.

Se un thread fa una biblioteca chiamare un che scrive un valore in un flusso e, di conseguenza, un altro thread legge questo valore dal flusso attraverso una chiamata di libreria b tale che questo non si traduca in un dato gara, quindi la scrittura di a si sincronizza con b's read.

Questo significa che se si scrive su un flusso, un blocco (non file di blocco, ma l'accesso simultaneo di bloccaggio per la struttura di dati flusso in memoria) è fatto, per essere sicuri che la concorrenza è ben manageged per tutta la altri thread che utilizzano lo stesso flusso.

Questo overhead di blocco è sempre lì, anche se non necessario. Ciò potrebbe avere un aspetto prestazionale, secondo Microsoft:

le prestazioni delle librerie multithread è stata migliorata e è vicino alle prestazioni delle ormai eliminate librerie thread singolo. Per quelle situazioni in cui sono richieste prestazioni ancora più elevate è richiesto , ci sono diverse nuove funzionalità.

Ecco perché vengono fornite le funzioni di _nolock. Accedono allo stream direttamente senza thread lock. Deve essere utilizzato con estrema cura, per esempio:

  • se l'applicazione è a thread singolo (un altro processo utilizzando lo stesso flusso ha una propria struttura di dati, e OS manageds concorrenza qui)
  • se si è sicuri che non ci sono due thread che usano lo stesso stream (per esempio se hai un solo thread di lettura e la scrittura è fatta al di fuori del tuo porgramme).
  • se si dispone di altro meccanismo di sincronizzazione che protegge una sezione critica del codice. Ad esempio, se si utilizza un blocco mutex o un algoritmo non bloccante thread-safe che fa uso di atomics.

In questi casi, il blocco aggiuntivo per l'accesso al flusso non è necessario/ridondante. Per le funzioni ad alta intensità di file, potrebbe valere la pena utilizzare il no_lock.

Nota: come si è sottolineato: vale la pena utilizzare il nolock per gli accessi di file intensivi in ​​cui si effettuano milioni di accessi.

0

fread_no_lock() sembra essere usato una volta che ci si assicura che il file sia bloccato con un meccanismo esterno (qualche forma di mutex, probabilmente), e quindi si usa per ridurre l'overhead: related: What's the intended use of _fread_nolock, _fseek_nolock?

Questo può anche rispondere a qualsiasi ulteriore domanda che potresti avere: potrebbe o non potrebbe essere possibile per il tuo disco rigido eseguire effettivamente più operazioni di I/O contemporaneamente a seconda di che tipo di disco rigido hai: https://superuser.com/questions/252959/which-is-faster-copying-everything-at-once-or-one-thing-at-a-time

+0

Ho visto la domanda "Qual è l'uso previsto di ..." prima di pubblicare e sono rimasto confuso. L'O/P dice che la funzione "the" (thinking means fread) blocca le chiamate re-enterant, consentendo ad un thread di essere nella funzione come un tutto alla volta. Ma una risposta indica che il blocco è invece al livello FILE *. Un'altra risposta dice che le versioni thread safe sono rientranti, ma non è possibile chiamarne due con lo stesso FILE *. Un'altra risposta dice prestazioni migliori usando le versioni _nolock, ma non menziona se l'I/O del disco reale è più alto, o se sta semplicemente bypassando i blocchi ridondanti. Mi ha lasciato con più domande. – user1902689