ProgrammazioneSviluppatore System/backend e Embedded

Parla delle regole di utilizzo delle variabili globali (static) in Rust. Come viene garantita la sicurezza durante l'accesso simultaneo e quali sono le differenze tra i vari modi di inizializzazione e sincronizzazione?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Rust, le variabili globali sono dichiarate utilizzando la parola chiave static. Queste variabili vivono per tutta la durata dell'esecuzione del programma. Per impostazione predefinita, l'accesso a static non mutabili è sicuro, ma per quelli mutabili è necessario usare unsafe, poiché il compilatore non può garantire l'assenza di condizioni di gara tra i thread.

Per un accesso sicuro alle variabili globali mutabili si utilizzano tipi di involucro speciali: Mutex, RwLock, tipi Atomic* o crate esterni (lazy_static, once_cell). L'inizializzazione è "pigra" se richiede la creazione ritardata dell'oggetto al primo accesso.

Esempi:

static COUNTER: AtomicUsize = AtomicUsize::new(0); static ref CONFIG: Config = read_config(); // con lazy_static o once_cell

Domanda trabocchetto

È possibile dichiarare una variabile globale mutabile senza tipi speciali, se verrà utilizzata solo da un singolo thread? È necessario scrivere unsafe?

Risposta: Il compilatore richiederà l'utilizzo di unsafe per qualsiasi modifica della variabile globale, anche se la logica è uniplo. Questo è un requisito generale per tutti i static mut. Solo se la variabile è avvolta in una struttura di sincronizzazione (Mutex, atomi, ecc.), il compilatore consentirà un accesso sicuro.

static mut VALUE: i32 = 0; unsafe { VALUE += 1; }

Esempi di errori reali a causa della mancanza di comprensione delle sfumature del tema


Storia

Nel web service, durante l'inizializzazione della cache globale, utilizzavano una normale variabile static con una stringa. Più thread scrivevano contemporaneamente, si verificavano "bit" di memoria e crash dell'applicazione a causa di condizioni di gara.


Storia

Nella utility di comando in Rust, cambiavano una variabile statica senza sincronizzazione, perché "funziona solo attraverso main". Successivamente, il codice è stato ritoccato per la multithreading, dimenticando lo stato globale mutabile, portando a bug molto difficili da individuare.


Storia

Nel programma embedded, inizializzavano in modo errato static CONFIG tramite una funzione all'avvio, ma non garantivano che fosse chiamata esattamente una volta. Di conseguenza, alcune parti del codice accedevano a una configurazione non inizializzata (riferimento nullo).