SemaphoreSlim释放方案对比:哪种实现方式更高效?
SemaphoreSlim两种释放实现的对比与正确性分析
首先看信号量实例代码:
private static readonly SemaphoreSlim _updateTokenLocker = new (1, 1);
第一种实现(正确写法)
await _updateTokenLocker.WaitAsync(); try { if (DateTime.UtcNow >= _tokenExpirationDateTime.AddMinutes(-5)) { var newToken = await GetTokenAsync(); return newToken; } } finally { _updateTokenLocker.Release(); }
这是SemaphoreSlim的标准正确用法:
finally块能确保无论try块内代码是正常执行、提前return还是抛出异常,信号量都会被释放,不会出现锁资源泄漏的情况。- 性能上几乎没有额外负担,
finally的执行开销可以忽略不计。
第二种实现(存在致命问题)
await _updateTokenLocker.WaitAsync(); if (DateTime.UtcNow >= _tokenExpirationDateTime.AddMinutes(-5)) { var newToken = await GetTokenAsync(); _updateTokenLocker.Release(); return newToken; }
这种写法完全不可用,存在严重的死锁风险:
- 当
if条件不满足时,代码不会执行Release(),信号量会一直被占用,后续所有调用WaitAsync()的线程都会永久等待,造成死锁。 - 如果
GetTokenAsync()抛出异常,同样不会执行Release(),锁资源直接泄漏。
关于效率的结论
两种写法在正常路径下的执行效率几乎没有差异,但第二种写法的正确性完全无法保障,根本没有讨论效率的意义。实际开发中必须使用第一种基于try/finally的写法。
内容的提问来源于stack exchange,提问作者Negin
相关产品推荐
相关产品推荐

