Respostas:
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?
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.
É muito mais um loop que continua até que uma determinada condição seja satisfeita:
while(cantGoOn) {};
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).
while(something != TRUE ){};
// it happend
move_on();
É 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 .
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
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.
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.
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.
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.