Perché si tratta di più thread considerati difficili? [duplicare]

1

Puoi dire che si basa sull'opinione pubblica, ma il problema è che l'opinione di tutti su questo problema è la stessa.

Anche gli sviluppatori principali sostengono che creare i thread è facile, trattare con loro è difficile. Non è un lavoro da principiante.

Tutto quello che so è che per gestire i thread devi bloccare tutti i dati condivisi fino a quando ciascun thread termina di accedervi da solo (anziché essere interrotto dal kernel), quindi sbloccarlo.

Questo risolverà tutti i deadlock e le condizioni di gara. Non è vero?

Che punto mi manca qui?

    
posta CoffeeDay 14.12.2015 - 09:34
fonte

4 risposte

4

Il blocco degli oggetti può essere la causa dei deadlock se non stai attento. Supponiamo che tu abbia due strutture dati A e B che hanno bisogno di avere dati sincronizzati. Il thread 1 aggiorna A con nuove informazioni, quindi aggiorna B in modo che corrisponda. Thread 2 aggiorna B con nuove informazioni, quindi aggiorna A in modo che corrisponda.

Quindi il flusso di lavoro per il thread 1 potrebbe essere:

 1. Receive new data.
 2. Lock A.
 3. Update A.
 4. Lock B.
 5. Update B to match.
 6. Unlock B.
 7. Unlock A.
 8. Goto 1.

Nota che A e B sono bloccati contemporaneamente, quindi qualcun altro non modifica B finché non abbiamo sincronizzato le nostre modifiche tra i due.

Supponiamo che i thread 1 e 2 ricevano entrambe le nuove allo stesso tempo e necessitino di aggiornare le strutture di dati. L'ordine in cui le cose potrebbero accadere è totalmente imprevedibile, ma potrebbe essere:

 1. Thread 1 locks A
 2. Thread 1 updates A
 3. Thread 2 locks B
 4. Thread 2 updates B
 5. Thread 1 now needs to update B, so it tries to lock B.  B is already locked so it waits.
 6. Thread 2 now needs to update A, so it tries to lock A.  A is already locked so it waits.
 7. Oops - deadlock.  The whole program is now permanently stuck.
    
risposta data 14.12.2015 - 09:58
fonte
13

La programmazione simultanea è difficile, in particolare perché devi affrontare i problemi di sincronizzazione.

All I know is that to deal with threads you have to lock all shared data till each thread finishes accessing it on its own (rather than getting interrupted by kernel), and then unlock it.

Non ne sai abbastanza sui thread. Leggi alcuni tutorial sui thread POSIX . Non devi solo utilizzare mutex , ma dovresti evitare deadlocks , e probabilmente hai bisogno di variabili di condizione .

E in pratica, trovare buoni compromessi è difficile (vedi la tabella qui per cogliere i tempi tipici delle operazioni ). Il blocco della granularità conta molto (probabilmente non vuoi bloccare e sbloccare alcuni mutex ogni due righe).

A livello di hardware, coerenza della cache è importante in processori multi-core e modelli di memoria , l'ordine di memoria è difficile da capire. In pratica, un sistema multi-core non si comporta in modo "intuitivo" w.r.t. tempo (in altre parole, ogni core potrebbe avere la propria nozione di tempo e orologio).

    
risposta data 14.12.2015 - 09:37
fonte
4

Come al solito, c'è un compromesso. Fare tutto in un thread è semplice e privo di rischi. Fare cose in più thread aumenta le prestazioni, ma introduce il rischio di errori di coerenza. L'utilizzo di blocchi per evitare tali errori può annullare l'intero vantaggio prestazionale per il quale hai introdotto thread in primo luogo.

In altre parole, la mantenibilità, le prestazioni e la correttezza formano una triade di requisiti, di cui solo due sono facili da soddisfare contemporaneamente. C'è un motivo per cui così tanti modelli alternativi di concorrenza vengono fatti galleggiare oggigiorno; il problema diventerà sempre più pressante in futuro, perché le CPU non diventano più veloci, solo più parallele, e il programmatore medio non è in grado di farne un uso produttivo con i nostri modelli esistenti.

    
risposta data 14.12.2015 - 09:41
fonte
3

blocca tutti i dati condivisi finché ogni thread termina di accedervi da solo

Questo è il bit difficile. Devi identificare correttamente tutti posti nel software in cui si accede ai dati condivisi. Devi quindi applicare i blocchi al livello di ambito corretto: se hai bloccato troppo, solo un thread sarà in grado di procedere (ad esempio il blocco dell'interprete globale di Python, GIL). Se blocchi / sblocca troppo frequentemente, ciò rallenterà il programma.

Spesso troverai alcune parti dell'architettura che sono molto contese. Quindi si finisce per ridisegnare grandi aree del sistema per ridurre tale contesa.

    
risposta data 14.12.2015 - 14:57
fonte

Leggi altre domande sui tag