c#题例-2025-06-19 14:12:46
日期: 2025-06-19 分类: AI写作 9次阅读
好的!以下是一道专家级别的 C# 程序员逻辑面试题,涉及多线程、并发控制和性能优化方面的知识:
---
### **面试题:**
假设你正在开发一个高性能的 Web 服务,需要处理大量的并发请求。其中有一个核心功能是:每次用户请求时,系统需要根据用户的唯一标识(如 `UserId`)递增一个计数器,并返回当前的计数值。
要求:
1. 计数器必须是线程安全的。
2. 每个用户都有自己独立的计数器。
3. 必须能够支持高并发场景。
4. 尽量减少锁的使用以提高性能。
请设计并实现一个类 `UserCounter`,满足上述需求。以下是接口定义:
```csharp
public class UserCounter
{
public UserCounter() { }
// 根据 UserId 递增计数器并返回当前值
public int IncrementAndGet(string userId)
{
// 实现代码
}
}
```
**提示:**
- 可以考虑使用 `ConcurrentDictionary` 或其他线程安全的集合。
- 避免直接使用 `lock`,尽量选择更高效的同步机制(如 `Interlocked`)。
- 考虑如何在高并发下减少竞争。
---
### **解答思路:**
1. **线程安全的存储结构**:可以使用 `ConcurrentDictionary
2. **避免锁的竞争**:对于计数器的递增操作,可以使用 `Interlocked.Increment` 来保证原子性,而不需要显式加锁。
3. **懒加载与高效初始化**:只有当某个用户第一次调用时才为其初始化计数器,而不是预先为所有用户分配空间。
---
你可以尝试自己实现这段代码,然后再对比参考答案!
---
### **参考答案:**
```csharp
using System;
using System.Collections.Concurrent;
public class UserCounter
{
private readonly ConcurrentDictionary
new ConcurrentDictionary
public long IncrementAndGet(string userId)
{
if (string.IsNullOrEmpty(userId))
{
throw new ArgumentException("UserId cannot be null or empty.");
}
// 使用 AddOrUpdate 方法来确保线程安全
return _userCounters.AddOrUpdate(
userId,
_ => Interlocked.Increment(ref _dummy), // 初始化时设置为1
(_, currentValue) => Interlocked.Increment(ref currentValue) // 原子递增
);
}
// 辅助字段,用于演示 Interlocked 的用法
private long _dummy = 0;
}
```
---
### **扩展问题:**
1. 如果需要支持计数器的重置功能(即清零),该如何修改代码?
2. 如果系统中存在大量不活跃的用户,如何优化内存使用?
希望这道题目能帮助你更好地评估候选人的多线程编程能力和性能优化思维!
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:AI写作
上一篇:无
精华推荐