Cosa sono esattamente gli "spin-lock"?


108

Mi sono sempre chiesto cosa siano: ogni volta che ne sento parlare, immagini di dispositivi futuristici simili a volani mi ballano (rotolano?) Nella mia mente ...

Quali sono?

Risposte:


125

Quando si utilizzano blocchi regolari (mutex, sezioni critiche, ecc.), Il sistema operativo mette il thread nello stato WAIT e lo anticipa pianificando altri thread sullo stesso core. Ciò comporta una riduzione delle prestazioni se il tempo di attesa è molto breve, perché il thread ora deve attendere una prelazione per ricevere nuovamente il tempo della CPU.

Inoltre, gli oggetti del kernel non sono disponibili in ogni stato del kernel, come in un gestore di interrupt o quando il paging non è disponibile ecc.

Gli spinlock non causano prelazione ma aspettano in un ciclo ("rotazione") fino a quando l'altro core rilascia il blocco. Ciò impedisce al thread di perdere il suo quantum e continua non appena il blocco viene rilasciato. Il semplice meccanismo degli spinlock consente a un kernel di utilizzarlo in quasi tutti gli stati.

Ecco perché su una macchina single core uno spinlock è semplicemente un "disabilitare interrupt" o "aumentare IRQL" che impedisce completamente la pianificazione dei thread.

Gli spinlock alla fine consentono ai kernel di evitare "Big Kernel Lock" (un blocco acquisito quando il core entra nel kernel e viene rilasciato all'uscita) e hanno un blocco granulare sulle primitive del kernel, causando una migliore multi-elaborazione su macchine multi-core e quindi prestazioni migliori.

EDIT : È emersa una domanda: "Significa che dovrei usare gli spinlock quando possibile?" e cercherò di rispondere:

Come ho detto, gli Spinlock sono utili solo in luoghi in cui il tempo di attesa anticipato è più breve di un quantum (leggi: millisecondi) e la preemption non ha molto senso (ad esempio, gli oggetti del kernel non sono disponibili).

Se il tempo di attesa è sconosciuto o se sei in modalità utente, gli Spinlock non sono efficienti. Si consuma il 100% del tempo della CPU sul core in attesa mentre si controlla se è disponibile uno spinlock. Impedisci l'esecuzione di altri thread su quel core fino alla scadenza del tuo quantum. Questo scenario è realizzabile solo per brevi sequenze a livello di kernel e un'opzione improbabile per un'applicazione in modalità utente.

Ecco una domanda su SO che si rivolge a questo: Spinlock, quanto sono utili?


significa che dovrei fare spin-lock (invece di mutex, sezione critica ecc.) ove possibile?

1
qualcuno per favore mi corregga se sbaglio, ma uno spinlock non disabilita la prelazione (es. riprogrammazione). per il semplice motivo che, se lo spinlock è in attesa di una risorsa bloccata da un altro processo, a quel secondo processo deve essere data la possibilità di eseguire e di liberare la risorsa. oppure, l'esecuzione del secondo processo richiede l'anticipo del primo processo (rotazione).
user1284631

ciò che fa spinlock è invece che non cambia lo stato del processo da TASK_RUNNING a TASK_INTERRUPTIBLE (che è uno stato inattivo) e, quindi, non salva tutto su quel processo (memoria, cache e così via). invece, il processo di rotazione viene anticipato, ma non esce mai dai processi "immediatamente schedulabili": viene mantenuto in memoria e gli altri processi vengono eseguiti regolarmente finché uno di essi non libera la risorsa che lo spinner sta aspettando: in quel momento, il spinlock ritorna semplicemente e il processo di filatura può continuare. attende in uno stato sempre TASK_RUNNING.
user1284631

1
hai ragione su questo (vedi anche questo: linuxjournal.com/article/5833 ), ma il fatto è che bloccare una risorsa e disabilitare gli interrupt, sebbene utili da eseguire congiuntamente, sono concetti altrimenti non correlati. fondamentalmente vuoi essere sicuro di non utilizzare una risorsa trovata in uno stato incoerente, e questo è il motivo per cui provi il suo blocco. disabilitare gli interrupt (anche la prelazione) assicura che sì, nessuno rovinerà la tua risorsa mentre ne hai a che fare. ma, per questo, devi essere sicuro che la risorsa sia gratuita quando la acquisisci.
user1284631

1
(quindi disabilita gli interrupt solo per essere sicuro che nessun'altra attività ti stia ostacolando e interferisca con la risorsa). su UP (uniprocessore), questo è sempre il caso: il primo spinlock (e quelli successivi) viene semplicemente concesso, gli interrupt (cioè la preemption) sono disabilitati e il task che utilizza la risorsa non viene mai anticipato: fa tutto il suo lavorare con la risorsa, quindi abilitare gli interrupt (e, quindi, la prelazione). quando la prelazione è abilitata, la risorsa è già gratuita. fondamentalmente, su UP, non ci sono contese di spinlock e non ci sono attese . su SMP potrebbe essere.
user1284631

25

Supponiamo che una risorsa sia protetta da un blocco, un thread che desidera accedere alla risorsa deve prima acquisire il blocco. Se il blocco non è disponibile, il thread potrebbe controllare ripetutamente se il blocco è stato liberato. Durante questo tempo il thread occupato attende, controllando il blocco, utilizzando la CPU, ma senza svolgere alcun lavoro utile. Tale blocco è definito come un blocco di rotazione.


2
Bella risposta! +1
Jayesh Bhoi

18

È piuttosto un ciclo che continua fino a quando non viene soddisfatta una certa condizione:

while(cantGoOn) {};

1
E / o while (cantGoOn) {sleep (0)};
Jiminion

@ Jiminion, se metti un sleep(0), si anticipa il thread, eliminando lo scopo di usare uno spinlock in primo luogo. se hai bisogno di cedere ad altri thread, dovresti usare un normale blocco. (So ​​che il tuo commento è molto vecchio ma volevo impedire ad altri di vederlo come un suggerimento).
Sedat Kapanoglu

"Un valore pari a zero fa sì che il thread ceda il resto del suo intervallo di tempo a qualsiasi altro thread pronto per l'esecuzione. Se non ci sono altri thread pronti per l'esecuzione, la funzione ritorna immediatamente e il thread continua l'esecuzione."
Jiminion


5

È un tipo di serratura che fa attesa occupata

È considerato un anti-pattern, tranne che per la programmazione di driver di livello molto basso (dove può accadere che chiamare una funzione di attesa "corretta" abbia più overhead del semplice blocco occupato per alcuni cicli).

Vedi ad esempio Spinlock nel kernel Linux .


3

Gli SpinLock sono quelli in cui il thread attende che il blocco sia disponibile. Questo sarà normalmente usato per evitare il sovraccarico di ottenere gli oggetti del kernel quando c'è lo scopo di acquisire l'oggetto del kernel entro un breve periodo di tempo.

Ex:

While(SpinCount-- && Kernel Object is not free)
{}

try acquiring Kernel object

3

Vorresti usare uno spinlock quando pensi che sia più economico entrare in un ciclo di attesa occupato e mettere in comune una risorsa invece di bloccare quando la risorsa è bloccata.

La rotazione può essere utile quando i blocchi sono a grana fine e in numero elevato (ad esempio, un blocco per nodo in un elenco collegato) e quando i tempi di blocco dei blocchi sono sempre estremamente brevi. In generale, mentre si tiene uno spin lock, si dovrebbe evitare di bloccare, chiamare tutto ciò che esso stesso potrebbe bloccare, mantenere più di uno spin lock contemporaneamente, effettuare chiamate inviate dinamicamente (interfaccia e virtuali), effettuare chiamate inviate staticamente in qualsiasi codice che non si fa ' possedere o allocare memoria.

È anche importante notare che SpinLock è un tipo di valore, per motivi di prestazioni. Pertanto, bisogna stare molto attenti a non copiare accidentalmente un'istanza SpinLock, poiché le due istanze (l'originale e la copia) sarebbero quindi completamente indipendenti l'una dall'altra, il che probabilmente porterebbe a un comportamento errato dell'applicazione. Se un'istanza SpinLock deve essere passata, dovrebbe essere passata per riferimento anziché per valore.


1

In poche parole, spinlock utilizza atomic compare and swap (CAS) o test-and-set come istruzioni per implementare l'idioma thread-safe senza blocco e in attesa. Tali strutture scalano bene nelle macchine multi-core.


Per definizione, uno spinlock non viene utilizzato per implementare nulla di lock free o di wait free.
rdb

0

È un ciclo che gira finché non viene soddisfatta una condizione.


0

Ebbene, sì - il punto di spin lock (rispetto alle sezioni critiche tradizionali, ecc.) È che offrono prestazioni migliori in alcune circostanze (sistemi multicore ..), perché non producono immediatamente il resto del quantum del thread.


0

Spinlock, è un tipo di blocco, che non è in grado di bloccare e non è in grado di dormire. Qualsiasi thread che desidera acquisire uno spinlock per qualsiasi risorsa condivisa o critica girerà continuamente, sprecando il ciclo di elaborazione della CPU fino a quando non acquisisce il blocco per la risorsa specificata. Una volta acquisito lo spinlock, cerca di completare il lavoro nel suo quantum e quindi rilasciare rispettivamente la risorsa. Spinlock è il tipo di blocco con la priorità più alta, si può semplicemente dire che è un tipo di blocco non preventivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.