Sincronização com locks
Last updated
Last updated
O sistema operacional fornece algumas primitivas para construção de mecanismos de sincronização (locks), como futex e instruções atômicas. Entretanto, essas primitivas são muito genéricas e requerem uma implementação mais robusta de lock, pois o Kernel obedece um design minimalista e tenta não impor nenhum mecanismo de lock, deixando que diferentes linguagens de programação possam implementar diferentes tipos de locks.
Vários tipos de locks podem ser implementados, mas vamos explicar brevemente o conceito de dois: spinlock e mutex.
Um lock baseado na técnica "busy-waiting", que é precisamente um loop onde a thread verifica o valor de uma variável compartilhada atomicamente. O spinlock não causa troca de contexto de threads, mas pode provocar um aumento do uso de CPU devido ao loop.
Mutex refere-se a mutual exclusion, ou exclusão mútua, onde a thread é colocada em um estado de (wait) até que o recurso seja liberado por outra thread (wake). Isto pode ser implementado por meio de thread signaling, que são basicamente sinais que podemos enviar às threads.
A vantagem é que a CPU não é consumida durante o tempo de espera da thread, porém há uma latência maior devido à troca de contexto das threads. E também pode-se gerar um problema onde duas ou mais threads ficam bloqueadas pra sempre por conta de um lock mal utilizado ou "perdido", que se chama deadlock.
Com mutex, podemos fazer com que a thread que chegou primeiro tenha acesso exclusivo ao recurso. Qualquer outra thread que tentar acessar o mesmo recurso, seja pra leitura ou escrita, vai ter que esperar o lock ser liberado...
Existem outros tipos de locks, como semáforos e rwlocks, mas por enquanto vamos deixar apenas esses dois, pelo que na segunda parte do guia abordaremos em detalhes a implementação de locks em cada linguagem.
Entretanto, podemos implementar alternativas em cenários de concorrência de modo a evitar o uso de locks. Quando o compartilhamento de memória e uso de locks passa a ser um grande problema, uma alternativa é implementar algumas "peças" de concorrência onde o estado não é compartilhado e a comunicação entre diferentes peças passa a ser através do envio de mensagens. Estamos falando do modelo de atores.