Kural
İstisna durumlarında bile kilitleri (locks) serbest bırakın.
İstisnalar oluştuğunda bile, her kilit edinimi garantili
bir serbest bırakma mekanizmasına sahip olmalıdır.
Desteklenen diller:** Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonGiriş
Serbest bırakılmayan kilitler (locks), canlı (production) Node.js uygulamalarında kilitlenmelerin (deadlocks) ve sistem donmalarının en yaygın nedenlerinden biridir. Kilit alımı ile serbest bırakılması arasında bir istisna oluştuğunda, kilit süresiz olarak tutulmaya devam eder. Bu kilidi bekleyen diğer asenkron işlemler sonsuza kadar askıda kalır ve sistem genelinde ardışık (cascading) hatalara yol açar. Serbest bırakılmamış tek bir mutex bile event loop'un bloke olması ve isteklerin birikmesi nedeniyle tüm bir API'yi çökletebilir. Bu durum, bunun gibi kütüphanelerde veya serbest bırakma işleminin otomatik olmadığı herhangi bir manuel kilit uygulamasında yaşanır: async-mutex, mutexify.
Neden önemli?
Sistem kararlılığı ve erişilebilirliği: Serbest bırakılmayan kilitler, Node.js'deki asenkron işlemleri donduran kilitlenmelere (deadlock) neden olur. Express veya Fastify sunucularında bu durum, mevcut worker'ları tüketerek uygulamanın yeni istekleri karşılayamamasına yol açar. Tek kurtuluş yolu, kesinti sürelerine (downtime) neden olan süreci yeniden başlatmaktır. Mikro servis mimarilerinde, bir servisteki serbest bırakılmamış kilitler, yanıt beklerken zaman aşımına uğrayan bağımlı servisler genelinde hataları tetikleyebilir.
Performans düşüşü: Tam kilitlenmeden önce, serbest bırakılmayan kilitler ciddi performans sorunlarına yol açar. Asenkron işlemler kilitli kaynaklar için yarışır ve asla çözümlenmeyen bekleyen promise'lerden oluşan bir kuyruk oluşturur. Kilit çekişmesi (lock contention), kullanıcı deneyimini olumsuz etkileyen öngörülebilir gecikme sıçramalarına (latency spikes) neden olur. Yük altında eşzamanlı istek sayısı arttıkça çekişme katlanarak artar.
Hata ayıklama karmaşıklığı: Serbest bırakılmayan kilitlerden kaynaklanan kilitlenmelerin canlı Node.js uygulamalarında hata ayıklaması son derece zordur. Belirtiler kök nedenden oldukça uzakta ortaya çıkar; askıda kalan süreçler bekleyen promise'leri gösterir ancak kilidi serbest bırakmayı hangi istisna yolunun başaramadığını göstermez. Kilitlenmeyi tetikleyen tam istisna dizisini geliştirme ortamlarında yeniden oluşturmak genellikle imkansızdır.
Kaynak tükenmesi: Kilitlerin kendisinin ötesinde, kilitleri serbest bırakmamak genellikle veritabanı bağlantıları, Redis istemcileri veya dosya tanıtıcıları (file handles) gibi diğer kaynakları serbest bırakmamakla ilişkilidir. Bu durum sorunu büyüterek sistemlerin yük altında daha hızlı çökmesine neden olan çok sayıda kaynak sızıntısı yaratır.
Kod örnekleri
❌ Kural dışı:
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();
}
Güvensiz olma nedeni: Yetersiz bakiye hatası fırlatılırsa, accountMutex.release() asla çalışmaz ve mutex sonsuza kadar kilitli kalır. Sonraki tüm çağrılar transferFunds() mutex'in serbest bırakılmasını bekleyerek askıda kalacak ve tüm ödeme sistemini donduracaktır.
✅ Kurallara uygun:
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();
}
}Neden güvenli? The catch bloğu, hatayı yeniden fırlatmadan önce bağlamıyla birlikte kaydeder (loglar) ve finally bloğu, işlem başarılı olsun, bir hata fırlatsın veya hata catch bloğundan yeniden fırlatılsın, mutex serbest bırakma fonksiyonunun çalışmasını garanti eder. Kilit her zaman serbest bırakılır ve kilitlenmeler önlenir.
Sonuç
Kilit serbest bırakma işlemi, başarılı yürütmeye koşullu değil, garantili olmalıdır. JavaScript'te try-finally bloklarını veya bunun gibi kütüphaneler tarafından sağlanan runExclusive() yardımcı aracını kullanın async-mutex. Her kilit alımının, aynı kod bloğunda görünür koşulsuz bir serbest bırakma yolu olmalıdır. Uygun kilit yönetimi isteğe bağlı değildir; kararlı bir sistem ile yük altında rastgele askıda kalan bir sistem arasındaki farktır.

