Condivisione del buffer tra più thread

3

Ho avuto un processo di lavoro che stava eseguendo un sacco di IO per leggere e scrivere file temporanei.
Ora voglio (necessario) ridurre la quantità di esecuzioni di I / O.

Quindi voglio creare una sorta di buffer circolare che verrà riempito con i dati di un file di testo nel primo thread.

Il thread del consumatore (in lettura) recupererà i dati da questo buffer.

Il problema è che potrebbero esserci più utenti che devono leggere dallo stesso buffer.

Per l'implementazione del buffer preferisco non utilizzare alcun wrapper esistente (array semplice, dove ho appena "giocato" con gli indici è sufficiente).

Inoltre non voglio creare un buffer separato per ogni lettore. E naturalmente voglio evitare qualsiasi deadlock e blocco non necessario.

Aggiorna
In questo momento sto usando un buffer circolare (un array e 2 indici)

La domanda è come implementare tale buffer a cui possono accedere più utenti in cui ogni consumatore può leggere da esso in modo interdipendente da altri consumatori (un cliente può leggere più velocemente dell'altro).

AGGIORNAMENTO IMPORTANTE
Il primo thread non sa (e non dovrebbe sapere) dei suoi consumatori !!! Dovrebbe scrivere i dati in un buffer, quando i dati terminano dovrebbe sollevare un flag.

    
posta kenny 04.12.2011 - 13:44
fonte

5 risposte

3

L'utilizzo di un array nudo ti costringe a fare più lavoro del necessario. Le persone hanno impiegato molto tempo a elaborare strutture di dati per semplificarti la vita, quindi usali.

Sembra che tu stia cercando di implementare una coda . Questa è una struttura dati che consente di aggiungere elementi alla raccolta e di rimuoverli in seguito. Questo viene fatto in un primo ordine in prima uscita. Java ha anche una coda thread-safe integrata. può semplicemente fare un'istanza di quella classe e dare a ciascuna delle tue discussioni un riferimento ad essa. Il produttore aggiungerà elementi alla coda e gli utenti rimuoveranno gli articoli dalla coda o eseguiranno un'altra azione se la coda è vuota.

Se hai davvero il coraggio di implementare tutto da solo, dovrai sincronizzare tutti gli accessi al tuo array in modo che due thread non possano accedere al buffer allo stesso tempo.

Modifica

Non era chiaro prima che tu volessi che ogni consumatore leggesse ogni bit di dati. Puoi estendere l'implementazione della coda in modo che tenga traccia del conteggio degli elementi (facendo size() di tempo costante) e poi generi un'eccezione se la coda è piena.

Per risolvere il problema dello schiocco è un po 'più complicato. È necessario tenere traccia dell'indice in cui si trova ogni consumatore, una mappa lo farebbe. Quindi, quando tutti gli utenti hanno spostato un articolo, è possibile scoppiare e aggiornare tutti gli indici nella mappa. Quando un consumatore chiama pop() e l'articolo deve essere conservato, puoi reindirizzarlo a peek() .

    
risposta data 04.12.2011 - 15:11
fonte
1

Sul lato Java guarda il disruptor che è una libreria di messaggistica interfoglia ad alto rendimento non bloccante . Ciò è in contrasto con la concorrenza 'tradizionale' basata sul blocco che la maggior parte della gente usa ancora con la programmazione Java / JVM. Lo stile che vuoi evitare nel tuo caso d'uso (perché gestire lo stato condiviso quando non devi).

    
risposta data 04.12.2011 - 17:24
fonte
0

Ho creato una classe come quella che descrivi in C ++, ma non in Java. Ho usato un modello singleton, combinato con modelli in modo che se conoscessi il tipo e la dimensione del buffer, otterrai l'istanza corretta. Quindi puoi avere diversi buffer di diversi tipi allo stesso tempo. Non sono sicuro che sarete in grado di farlo esattamente in Java o meno. Ma a prescindere da ciò, ciò che dico di seguito vale ancora.

Per quanto riguarda l'implementazione, avrai bisogno di alcuni semafori e mutex. Ho usato due semafori, uno per contare il numero di elementi nel buffer e uno per contare la quantità di spazio rimasto. Puoi quindi utilizzarli nei tuoi metodi put() e get() per determinare se c'è spazio o qualcosa da prendere. Una volta fatto, puoi prendere il mutex che protegge l'accesso al buffer, copiare il tuo oggetto e cambiare i puntatori dell'indice.

L'uso dei semafori evita il deadlocking sul mutex nello scenario in cui il thread getter lo acquisisce prima che il thread putter abbia inserito qualcosa nel buffer. Puoi utilizzare i puntatori dell'indice per implementare una funzione numItems() e ti serviranno per allenare gli indie dell'array da utilizzare per get e put.

    
risposta data 04.12.2011 - 15:45
fonte
0

The question is how to implement such buffer that can be accessed by multiple costumers where each costumer can read from it interdependently from other costumers (one costumer may read faster than the other one).

Per fare ciò in sicurezza, è necessario assicurarsi che solo un thread possa accedere al buffer in un dato momento. Questo può essere un problema complesso, ma i metodi sincronizzati di Java semplificano le cose per te. In poche parole, se un thread sta eseguendo un metodo sincronizzato di un oggetto, nessun altro metodo sincronizzato su quell'oggetto può essere eseguito in alcun thread fino al completamento di tale metodo.

Quindi, il tuo compito è creare una classe per il tuo buffer con metodi di lettura e scrittura sincronizzati. Crea un'istantanea di classe all'inizio del tuo programma e condividi l'oggetto risultante con tutti i produttori e i consumatori. La sincronizzazione dei metodi di Java garantirà che solo un thread acceda l'oggetto alla volta.

    
risposta data 04.12.2011 - 17:31
fonte
0

che cosa dice unholysampler + DEVI conoscere tutti i consumatori (perché senza di esso non sai se tutti loro leggono effettivamente qualche byte), e se ce n'è uno che legge più lentamente di altri (e di quello che produce il produttore), terminerai con un array completo non letto da lui.

Puoi o 1) dal lato produttore: lancio o blocco 2) rimuovilo come consumatore e inizia la sua coda (ma usa qualcosa che può crescere) 3) rimuovilo come consumatore e genera un'eccezione quando vuole leggere.

    
risposta data 09.12.2011 - 18:52
fonte

Leggi altre domande sui tag