Come impedire ad altri utenti di utilizzare variabili non thread-safe in un ambiente multithreading?

7

Ho un'applicazione scritta in C ++ che era originariamente a thread singolo, ma, a causa della crescente complessità di questo progetto, avrò bisogno di espanderlo ad almeno due o tre thread.

Ci sono solo un totale di quattro variabili che saranno usate tra più thread di thread, rendendo inutile rendere tutto thread-safe. La soluzione ovvia è semplicemente creare un mutex per ogni variabile e andare avanti con la mia vita.

Tuttavia, guardando indietro, sembra un'idea orribile! Ho paura che un altro programmatore possa dimenticare che la maggior parte dei metodi e delle variabili non sono thread-safe e utilizzano una variabile in un altro thread.

Dato che sono il programmatore principale di questo progetto, non sembra che questo sarebbe un problema, ma onestamente sento che questa è una programmazione sbagliata e mi sembra davvero complicato.

Quali sono alcuni modi per tenere separate le variabili per rendere più facile stabilire quale variabile è per quale thread? Stavo pensando di isolare il codice per il thread in modo che non possa accedere alle altre variabili globali (dando un errore di compilazione invece di creare silenziosamente un bug). Potrei anche creare uno spazio dei nomi o una classe per ogni thread. Esiste una best practice per questo?

    
posta Anonymous Penguin 22.11.2014 - 04:57
fonte

4 risposte

3

Ci sono due elementi a questo problema: # 1, la modifica tecnica alla base di codice esistente per supportare il multithreading e # 2 cambiare la cultura dell'azienda per essere al corrente della sicurezza del thread nel codice.

Il primo è relativamente semplice. In primo luogo, documentare le funzioni della classe che sono thread-safe e non sono thread-safe. Sono d'accordo con Jeffery Thomas che dovresti considerare come una nuova importante funzionalità. Spesso scriverò una classe completamente nuova con alcuni (rispetto alla classe originale per tenerla ASCIUTTA) che è thread-safe. Sebbene non ci sia un tag "thread safe" esplicito in c ++, trovo che rendere la classe const corretta possa fare molto per dare una mano. Dovresti anche documentare chiaramente qual è il thread sicuro o meno (seguire una convenzione, essere COERENTE e rendere lo stato assunto non thread-safe).

Il problema più grande sta cambiando la cultura dell'azienda per assicurarsi che tutti siano a conoscenza della sicurezza dei thread. Trovo che sia qui che cose come una guida di stile e recensioni di codice possono essere molto utili. Una guida di stile può informare le persone esattamente su come contrassegnare le cose come thread safe. Facciamo molta programmazione in C, quindi sono parziale nel decorare i nomi, ma dovresti scegliere uno stile che funzioni per te. Alcune aziende tendono a rendere tutto thread-safe di default, ma trovo che tende ad aggiungere un sacco di complessità inutile del codice, e può aggiungere occasionalmente un overhead non insignificante.

Le revisioni del codice, se fatte correttamente, sono un modo per educare tutti sullo stile e trasferire informazioni sulla programmazione in generale.

    
risposta data 25.11.2014 - 14:52
fonte
5

Avvolgi tutti gli accessi alle variabili in una funzione thread-safe in modo che l'accesso delle variabili da qualsiasi parte del codice passi attraverso un singolo metodo e rendi la variabile privata.

In questo modo qualsiasi accesso della variabile dall'esterno della classe sarà thread-safe.

Il prossimo passo è spostare le variabili nella loro classe, accessibile solo tramite i metodi sicuri. (Non una classe per variabile, solo tutte le variabili in una classe separata.)

C'è sempre un modo per un altro programmatore di rovinare il codice, ma nella mia esperienza se scrivi il codice in modo che la cosa più facile da fare per loro sia il modo sicuro, sarà quello che fanno.

    
risposta data 22.11.2014 - 18:04
fonte
3

L'aggiunta di multi-threading è una delle principali novità di una classe. Penso che dovresti trattarlo come una nuova importante funzione e non provare a introdurlo di nascosto.

Ripensare e ridefinire la classe e le sue relazioni. Vorrei esaminare la creazione di una nuova classe per rappresentare ogni attività threaded e / o una fetta di funzionalità.

Se necessario, puoi conservare la vecchia interfaccia di classe come proxy per il nuovo cluster di classi.

    
risposta data 22.11.2014 - 20:22
fonte
1

Dopo un po 'di lavoro, ho effettivamente trovato una soluzione semplice per questo problema (così semplice come si ottiene) ... namespace .

Ogni thread logico è organizzato in uno spazio dei nomi specifico. Ad esempio, questo è come appare la mia organizzazione dello spazio dei nomi (divisa in file diversi, ovviamente). Se avessi un sacco di altre cose condivise, avrei fatto un approccio di classe come risposta di SumGuy per le variabili condivise, ma sarebbe eccessivo farlo per tutto il codice poiché, oltre alle quattro variabili, i thread sono indipendenti.

namespace MainThread {

}

namespace ThreadOne {

}

Non è una soluzione carina, ma almeno un'altra persona dovrà digitare esplicitamente la parola "thread" per usare una variabile / funzione in un altro thread, quindi è colpa loro se ignorano una cosa così ovvia.

Inoltre, se si modifica il codice in uno spazio dei nomi, non richiede uno sforzo extra per digitare il nome del thread corrente dal momento che viene assunto automaticamente!

    
risposta data 31.01.2015 - 18:55
fonte

Leggi altre domande sui tag