c#题例-2025-08-02 04:18:42
日期: 2025-08-02 分类: AI写作 15次阅读
当然可以!下面是一道**专家级别**的 C# 程序员逻辑面试题,涉及 **闭包、异步编程、多线程、捕获变量、异常处理和TPL(任务并行库)** 的综合应用:
---
### 🧠 面试题:异步闭包与线程安全陷阱
**题目描述:**
请看以下 C# 控制台应用程序代码片段。该程序启动多个异步任务,并试图在每个任务中修改一个共享变量 `counter`,然后输出每个任务的索引值。
```csharp
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
int counter = 0;
for (int i = 0; i < 5; i++)
{
Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步工作
counter++;
Console.WriteLine($"Task {i} finished, counter = {counter}");
});
}
await Task.Delay(1000); // 等待所有任务完成
Console.WriteLine($"Final counter value: {counter}");
}
}
```
**问题:**
1. 程序的输出是否可靠?为什么?
2. 是否存在线程安全问题?请指出具体问题。
3. `Console.WriteLine($"Task {i} finished...")` 是否总是输出正确的 `i` 值?为什么?
4. 如何修改这段代码,使其线程安全并正确输出每个任务的索引?
---
### 💡 考察点:
- **闭包变量捕获陷阱(Closure Capturing)**
- **异步编程与TPL的使用**
- **线程安全性与竞态条件(Race Condition)**
- **int++ 的非原子性**
- **如何安全地在多线程环境中更新共享状态**
---
### ✅ 示例参考答案:
#### 1. 输出是否可靠?
不可靠。因为 `counter++` 是非原子操作,多个线程同时执行会引发竞态条件,导致最终的 `counter` 值可能小于预期的 5。
#### 2. 是否存在线程安全问题?
是的。`counter++` 不是原子操作,它包括读取、递增、写入三步。在多线程下,这可能导致值被覆盖或丢失。
#### 3. `i` 的输出是否正确?
不一定。由于在循环中直接使用了循环变量 `i`,所有任务可能捕获的是同一个变量引用,最终输出的 `i` 可能都是 5(循环结束后的值)。
#### 4. 如何修复?
```csharp
using System;
using System.Threading.Tasks;
using System.Threading;
class Program
{
static async Task Main()
{
int counter = 0;
object lockObj = new object();
for (int i = 0; i < 5; i++)
{
int localIndex = i; // 避免闭包陷阱
await Task.Run(async () =>
{
await Task.Delay(100); // 模拟异步工作
Interlocked.Increment(ref counter); // 原子操作
Console.WriteLine($"Task {localIndex} finished, counter = {counter}");
});
}
await Task.Delay(1000);
Console.WriteLine($"Final counter value: {counter}");
}
}
```
或使用 `Interlocked` 类来保证原子性,或使用 `lock` 语句同步访问。
---
### 📌 总结:
这道题不仅考察了基本语法,还深入到了 C# 的并发模型、闭包机制以及异步编程的最佳实践,是考察高级 C# 工程师逻辑思维和系统理解能力的很好题目。
如果你需要更多类似级别的题目(如涉及表达式树、反射、内存泄漏排查、GC机制、TPL进阶等),欢迎继续提问!
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
精华推荐