跳转到主要内容

锁的概念及应用场景

1、常见“锁”及使用方式一览表

锁类型
是否支持异步
官方定义
适用场景
面试考点
Lock
❌ 否
提供基于对象的互斥访问机制(Monitor 实现)
小范围共享资源保护
不可在 lock 中 await、死锁问题、Monitor 底层实现
Monitor
❌ 否
提供与 lock 相同功能,底层机制
自定义细粒度控制
Wait/Pulse 使用、Enter/Exit 注意 try-finally
Mutex
✅ 是(跨进程)
基于操作系统内核对象的互斥锁
跨进程同步、防止程序多开
性能低、WaitOne、释放所有权

Semaphore

SemaphoreSlim

✅ 是
控制最多允许 n 个线程同时访问
限流、异步资源池、队列控制
Slim 更轻量、WaitAsync 支持异步
ReaderWriterLockSlim
✅ 是
允许多个读线程、一个写线程
读多写少(如缓存)
EnterReadLock / WriteLock、性能优化

SpinLock

SpinWait

❌ 否
忙等锁,适合极短等待时间
极端高性能场景
CPU 浪费风险、自旋次数控制
Concurrent Collections
N/A
内部已实现线程安全的集合类
多线程数据结构操作
如何选择 ConcurrentDictionary 等
Channel<T>
✅ 是
生产者消费者模型通信机制
任务队列、事件流处理
Bounded vs Unbounded、异步消费

2、各种锁代码案例

Lock
private readonly object _sync = new object();

public void UpdateState()
{
    lock (_sync)
    {
        // 同步操作
    }
}
Monitor
Monitor.Enter(_sync);
try
{
    // 同步代码
}
finally
{
    Monitor.Exit(_sync);
}
Mutex
var mutex = new Mutex(false, "MyAppUniqueName");
if (mutex.WaitOne(TimeSpan.FromSeconds(3), false))
{
    try
    {
        // 访问共享资源
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}
SemaPhore/SemaPhoreSlim
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);

public async Task AccessResourceAsync()
{
    await _semaphore.WaitAsync();
    try
    {
        // 异步访问资源
    }
    finally
    {
        _semaphore.Release();
    }
}
ReaderWriterLockSlim
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();

public void ReadData()
{
    _rwLock.EnterReadLock();
    try
    {
        // 读取数据
    }
    finally
    {
        _rwLock.ExitReadLock();
    }
}

public void WriteData()
{
    _rwLock.EnterWriteLock();
    try
    {
        // 写入数据
    }
    finally
    {
        _rwLock.ExitWriteLock();
    }
}
SpinLock/SpinWait
SpinLock spinLock = new SpinLock();
bool lockTaken = false;
try
{
    spinLock.Enter(ref lockTaken);
    // 操作共享资源
}
finally
{
    if (lockTaken) spinLock.Exit();
}
Concurrent Collections
ConcurrentDictionary<string, string> cache = new ConcurrentDictionary<string, string>();
cache.TryAdd("key", "value");

ConcurrentQueue<int> queue = new ConcurrentQueue<int>();
queue.Enqueue(1);
Channel<T>
var channel = Channel.CreateUnbounded<int>();

// 生产者
await channel.Writer.WriteAsync(1);

// 消费者
await foreach (var item in channel.Reader.ReadAllAsync())
{
    Console.WriteLine(item);
}