Javascript é definido como uma linguagem reentrante , o que significa que não há threading exposto ao usuário, pode haver threads na implementação. Funções como setTimeout()
callbacks assíncronos precisam esperar o mecanismo de script dormir antes de serem executados.
Isso significa que tudo o que acontece em um evento deve ser concluído antes que o próximo evento seja processado.
Dito isso, você pode precisar de um mutex se seu código fizer algo em que espera que um valor não mude entre o momento em que o evento assíncrono foi disparado e o momento em que o retorno de chamada foi chamado.
Por exemplo, se você tiver uma estrutura de dados onde você clica em um botão e ele envia um XmlHttpRequest que chama um retorno de chamada, a estrutura de dados muda de forma destrutiva, e você tem outro botão que muda a mesma estrutura de dados diretamente, entre quando o evento foi disparado e quando o retorno de chamada foi executado, o usuário poderia ter clicado e atualizado a estrutura de dados antes do retorno de chamada, o que poderia então perder o valor.
Embora você possa criar uma condição de corrida como essa, é muito fácil evitar isso em seu código, pois cada função será atômica. Seria muito trabalhoso e alguns padrões de codificação estranhos para criar a condição de corrida de fato.