O que exatamente são “spin-locks”?


108

Sempre me perguntei o que são: toda vez que ouço falar deles, imagens de dispositivos futuristas em forma de volante vão dançando (rolando?) Em minha mente ...

O que eles são?

Respostas:


125

Quando você usa bloqueios regulares (mutexes, seções críticas, etc), o sistema operacional coloca seu thread no estado WAIT e o antecipa agendando outros threads no mesmo núcleo. Isso tem uma penalidade de desempenho se o tempo de espera for realmente curto, porque seu encadeamento agora tem que esperar por uma preempção para receber o tempo da CPU novamente.

Além disso, os objetos do kernel não estão disponíveis em todos os estados do kernel, como em um manipulador de interrupção ou quando a paginação não está disponível, etc.

Spinlocks não causam preempção, mas esperam em um loop ("giro") até que o outro núcleo libere o bloqueio. Isso evita que o segmento perca seu quantum e continue assim que o bloqueio for liberado. O mecanismo simples de spinlocks permite que um kernel o utilize em quase qualquer estado.

É por isso que em uma máquina de núcleo único um spinlock é simplesmente uma "desativação de interrupções" ou "aumento de IRQL", que impede o agendamento de thread completamente.

Em última análise, os spinlocks permitem que os kernels evitem "Big Kernel Lock" s (um bloqueio adquirido quando o núcleo entra no kernel e liberado na saída) e têm bloqueio granular sobre os primitivos do kernel, causando melhor multi-processamento em máquinas multi-core, portanto, melhor desempenho.

EDIT : Surgiu uma pergunta: "Isso significa que devo usar spinlocks sempre que possível?" e vou tentar responder:

Como mencionei, Spinlocks só são úteis em lugares onde o tempo de espera antecipado é menor do que um quantum (leia-se: milissegundos) e a preempção não faz muito sentido (por exemplo, objetos de kernel não estão disponíveis).

Se o tempo de espera for desconhecido ou se você estiver no modo de usuário, os Spinlocks não são eficientes. Você consome 100% do tempo de CPU no núcleo de espera enquanto verifica se um spinlock está disponível. Você evita que outros threads rodem naquele núcleo até que seu quantum expire. Este cenário só é viável para rajadas curtas no nível do kernel e uma opção improvável para um aplicativo de modo de usuário.

Aqui está uma pergunta sobre o SO abordando isso: Spinlocks, quão úteis são eles?


isso significa que devo girar os bloqueios (em vez de mutex, seção crítica etc.) sempre que possível?

1
alguém por favor me corrija se eu estiver errado, mas um spinlock não desabilita a preempção (ou seja, reprogramação). pela simples razão de que, se o spinlock está esperando por um recurso bloqueado por outro processo, esse segundo processo deve ter a chance de ser executado e liberar o recurso. ou, a execução do segundo processo requer antecipar o primeiro processo (girar).
user1284631

o que o spinlock faz é que não muda o estado do processo de TASK_RUNNING para TASK_INTERRUPTIBLE (que é um estado de hibernação) e, portanto, não salva tudo sobre esse processo (memória, cache e assim por diante). em vez disso, o processo de rotação é antecipado, mas nunca sai dos processos "imediatamente escalonáveis": é mantido na memória e os outros processos são executados regularmente até que um deles libere o recurso que o spinner está esperando: naquele momento, o spinlock simplesmente retorna e o processo de rotação pode continuar. ele espera em um estado sempre TASK_RUNNING.
user1284631

1
você está certo sobre isso (veja também: linuxjournal.com/article/5833 ), mas o fato é que bloquear um recurso e desabilitar interrupções, embora úteis para serem executadas em conjunto, são conceitos não relacionados. você basicamente quer ter certeza de que não está usando um recurso encontrado em um estado inconsistente e é por isso que você testa seu bloqueio. desabilitar interrupções (também preempção) garante que sim, ninguém mexerá com seu recurso enquanto você estiver lidando com ele. mas, para isso, você precisa ter certeza de que o recurso está livre quando você o adquirir.
user1284631

1
(então desative as interrupções apenas para ter certeza de que nenhuma outra tarefa está impedindo você e atrapalhando o recurso). no UP (uni-processador), este é sempre o caso: o primeiro (e os subseqüentes) spinlock é simplesmente concedido, interrupções (isto é, preempção) são desabilitadas e a tarefa que usa o recurso nunca é antecipada: ela faz todo o seu trabalho com o recurso e, em seguida, habilite as interrupções (e, portanto, a preempção). quando a preempção está habilitada, o recurso já está livre. basicamente, no UP, não há contenção de spinlock e não há espera . no SMP pode ser.
user1284631

25

Digamos que um recurso esteja protegido por um bloqueio, um thread que deseja acessar o recurso precisa primeiro adquirir o bloqueio. Se o bloqueio não estiver disponível, o thread pode verificar repetidamente se o bloqueio foi liberado. Durante esse tempo, o thread ocupado espera, verificando o bloqueio, usando a CPU, mas sem realizar nenhum trabalho útil. Esse bloqueio é denominado bloqueio de rotação.


2
Boa resposta! +1
Jayesh Bhoi

18

É muito mais um loop que continua até que uma determinada condição seja satisfeita:

while(cantGoOn) {};

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

@Jiminion se você colocar um, sleep(0)ele interromperá o thread, eliminando o propósito de usar um spinlock em primeiro lugar. se precisar ceder a outros threads, você deve usar um bloqueio regular. (sei que o seu comentário é muito antigo, mas queria evitar que outras pessoas vissem isso como uma sugestão).
Sedat Kapanoglu

"Um valor igual a zero faz com que o encadeamento ceda o restante de sua fatia de tempo para qualquer outro encadeamento que esteja pronto para ser executado. Se não houver outros encadeamentos prontos para serem executados, a função retorna imediatamente e o encadeamento continua a execução."
Jiminion de


5

É um tipo de fechadura que espera ocupada

É considerado um antipadrão, exceto para programação de driver de nível muito baixo (onde pode acontecer que chamar uma função de espera "adequada" tenha mais sobrecarga do que simplesmente travamento ocupado por alguns ciclos).

Veja, por exemplo, Spinlocks no kernel Linux .


3

SpinLocks são aqueles em que o thread espera até que o bloqueio esteja disponível. Isso normalmente será usado para evitar a sobrecarga de obtenção dos objetos do kernel quando houver um escopo de aquisição do objeto do kernel em um pequeno período de tempo.

Ex:

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

try acquiring Kernel object

3

Você gostaria de usar um spinlock quando achar que é mais barato entrar em um loop de espera ocupado e agrupar um recurso em vez de bloquear quando o recurso está bloqueado.

A rotação pode ser benéfica quando os bloqueios são refinados e grandes em número (por exemplo, um bloqueio por nó em uma lista vinculada), bem como quando os tempos de bloqueio do bloqueio são sempre extremamente curtos. Em geral, enquanto mantém um bloqueio de rotação, deve-se evitar o bloqueio, chamando qualquer coisa que possa bloquear, segurando mais de um bloqueio de rotação ao mesmo tempo, fazendo chamadas despachadas dinamicamente (interface e virtuais), fazendo chamadas despachadas estaticamente para qualquer código que não seja t possuir ou alocar memória.

Também é importante observar que SpinLock é um tipo de valor, por motivos de desempenho. Dessa forma, deve-se ter muito cuidado para não copiar acidentalmente uma instância SpinLock, pois as duas instâncias (a original e a cópia) seriam completamente independentes uma da outra, o que provavelmente levaria a um comportamento incorreto do aplicativo. Se uma instância SpinLock deve ser transmitida, ela deve ser transmitida por referência em vez de por valor.


1

Resumindo, o spinlock emprega instruções atômicas de comparação e troca (CAS) ou teste e ajuste para implementar o idioma seguro de thread livre de bloqueio e espera. Essas estruturas são bem dimensionadas em máquinas com vários núcleos.


Por definição, um spinlock não é usado para implementar qualquer coisa sem bloqueio ou sem espera.
rdb

0

É um loop que gira até que uma condição seja atendida.


0

Bem, sim - o ponto de bloqueio de rotação (versus seções críticas tradicionais, etc) é que eles oferecem melhor desempenho em algumas circunstâncias (sistemas multicore ..), porque eles não produzem imediatamente o resto do quantum do thread.


0

Spinlock é um tipo de bloqueio que não pode ser bloqueado e nem dormir. Qualquer thread que deseja adquirir um spinlock para qualquer recurso compartilhado ou crítico girará continuamente, desperdiçando o ciclo de processamento da CPU até adquirir o bloqueio para o recurso especificado. Uma vez adquirido o spinlock, ele tenta completar o trabalho em seu quantum e então liberar o recurso respectivamente. Spinlock é o tipo de bloqueio de prioridade mais alta, podemos simplesmente dizer, é o tipo de bloqueio não preventivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.