Regra
Libertação fechaduras mesmo em exceção caminhos.
Todos os bloqueio aquisição deve ter a garantida
libertação, mesmo quando excepções ocorrem.
Suportados linguagens suportadas:** Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonIntrodução
Locks não liberados são uma das causas mais comuns de deadlocks e travamentos de sistema em aplicações Node.js em produção. Quando uma exceção ocorre entre a aquisição e a liberação de um lock, o lock permanece retido indefinidamente. Outras operações assíncronas esperando por esse lock travam para sempre, causando falhas em cascata por todo o sistema. Um único mutex não liberado pode derrubar uma API inteira porque o event loop fica bloqueado e as requisições se acumulam. Isso acontece com bibliotecas como async-mutex, mutexify, ou qualquer implementação de bloqueio manual onde a liberação não é automática.
Por que isso importa
Estabilidade e disponibilidade do sistema: Locks não liberados causam deadlocks que congelam operações assíncronas no Node.js. Em servidores Express ou Fastify, isso esgota os workers disponíveis, tornando a aplicação incapaz de lidar com novas requisições. A única recuperação é reiniciar o processo, causando downtime. Em arquiteturas de microsserviços, locks não liberados em um serviço podem causar falhas em cascata em serviços dependentes, à medida que eles expiram esperando por respostas.
Degradação de desempenho: Antes do deadlock completo, locks não liberados causam problemas graves de desempenho. Operações assíncronas disputam recursos bloqueados, criando uma fila de promises pendentes que nunca se resolvem. A contenção de locks cria picos de latência imprevisíveis que degradam a experiência do usuário. À medida que o número de requisições concorrentes aumenta sob carga, a contenção se agrava exponencialmente.
Complexidade de depuração: Deadlocks de locks não liberados são notoriamente difíceis de depurar em aplicações Node.js em produção. Os sintomas aparecem longe da causa raiz, travamentos de processo mostram promessas pendentes, mas não qual caminho de exceção falhou em liberar o lock. Reproduzir a sequência exata de exceções que acionaram o deadlock é frequentemente impossível em ambientes de desenvolvimento.
Esgotamento de recursos: Além dos próprios locks, a falha em liberar locks frequentemente se correlaciona com a falha em liberar outros recursos, como conexões de banco de dados, clientes Redis ou manipuladores de arquivos. Isso agrava o problema, criando múltiplos vazamentos de recursos que derrubam os sistemas mais rapidamente sob carga.
Exemplos de código
❌ Não-conforme:
const { Mutex } = require('async-mutex');
const accountMutex = new Mutex();
async function transferFunds(from, to, amount) {
await accountMutex.acquire();
if (from.balance < amount) {
throw new Error('Insufficient funds');
}
from.balance -= amount;
to.balance += amount;
accountMutex.release();
}
Por que é inseguro: Se o erro de fundos insuficientes for lançado, accountMutex.release() nunca é executado e o mutex permanece bloqueado para sempre. Todas as chamadas subsequentes para transferFunds() ficará travado esperando pelo mutex, congelando todo o sistema de pagamento.
✅ Compatível:
const { Mutex } = require('async-mutex');
const accountMutex = new Mutex();
async function transferFunds(from, to, amount) {
const release = await accountMutex.acquire();
try {
if (from.balance < amount) {
throw new Error('Insufficient funds');
}
from.balance -= amount;
to.balance += amount;
} catch (error) {
logger.error('Transfer failed', {
fromId: from.id,
toId: to.id,
amount,
error: error.message
});
throw error;
} finally {
release();
}
}Por que é seguro: O Detectar O bloco registra o erro com contexto antes de relançá-lo, e o finalmente O bloco garante que a função de liberação do mutex seja executada, seja a operação bem-sucedida, lançando um erro, ou se o erro for relançado do catch. O lock é sempre liberado, prevenindo deadlocks.
Conclusão
A liberação do lock deve ser garantida, não condicional à execução bem-sucedida. Use try-finally blocos em JavaScript ou o runExclusive() auxiliar fornecido por bibliotecas como async-mutex. Toda aquisição de lock deve ter um caminho de liberação incondicional visível no mesmo bloco de código. O gerenciamento adequado de locks não é opcional, é a diferença entre um sistema estável e um que trava aleatoriamente sob carga.
.avif)
