在 C# 中,信号量是一种什么同步原语?请说明其工作原理,并给出使用 Semaphore 或 SemaphoreSlim 来限制对共享资源并发访问的典型步骤。
考察说明
考查对信号量概念及其在 C# 中具体用法的理解。
回答思路
- 【回答框架 1】信号量是用于控制同时访问共享资源的线程或进程数量的同步原语,内部维护一个计数器,当计数器大于零时允许访问并递减,否则调用者等待,释放时递增并唤醒等待者。
- 【回答框架 2】C# 中 Semaphore 可跨进程使用,SemaphoreSlim 更轻量且只限于进程内。使用时先通过构造参数指定初始计数和最大计数,资源访问前调用 WaitOne 或 Wait 获取许可,访问结束后在 finally 里调用 Release 释放。
- 【回答框架 3】信号量适合限制并发连接数或线程池大小等场景,但不保证公平性,也不负责业务逻辑的幂等控制,只解决互斥准入问题。
- 【回答框架 4】示例流程:创建 SemaphoreSlim(3, 3) 允许三个并发,每个任务先 await semaphore.WaitAsync() 再访问资源,最后 Release 并释放资源。
- 【回答框架 5】选择依据:需要跨进程同步用 Semaphore,仅在进程内且追求性能用 SemaphoreSlim。使用时应确保释放次数不超过初始计数,避免信号量计数异常。
- 【关键点 1】信号量通过计数限制并发访问数,非互斥锁,可允许多个许可。
- 【关键点 2】Semaphore 支持跨进程,SemaphoreSlim 面向进程内轻量场景。
- 【关键点 3】访问前后分别调用 WaitOne 或 Wait 和 Release,且在 finally 中释放保证可靠性。
- 【关键点 4】信号量只控制准入数量,不隐含业务幂等或一致性保证。
- 【易错点 1】忘记在 finally 中释放信号量可能导致死锁或资源耗尽。
- 【易错点 2】将信号量用于单一资源互斥时,计数应设为1,但信号量本身不提供所有权概念,可能导致误用。
- 【易错点 3】跨进程使用 Semaphore 时需注意命名和安全性,命名不当可能被其他进程误获取。