跳转到主要内容

锁的概念及应用场景

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

锁类型
是否支持异步
官方定义
适用场景
Lock
❌ 否
提供基于对象的互斥访问机制(Monitor 实现)
小范围共享资源保护
Monitor
❌ 否
提供与 lock 相同功能,底层机制
自定义细粒度控制
Mutex
✅ 是(跨进程)
基于操作系统内核对象的互斥锁
跨进程同步、防止程序多开

Semaphore

SemaphoreSlim

✅ 是
控制最多允许 n 个线程同时访问
限流、异步资源池、队列控制
ReaderWriterLockSlim
✅ 是
允许多个读线程、一个写线程
缓存、配置中心

SpinLock

SpinWait

❌ 否
忙等锁,适合极短等待时间
极端高性能场景
Concurrent Collections
N/A
内部已实现线程安全的集合类
多线程数据结构操作
Channel<T>
✅ 是
生产者消费者模型通信机制
任务队列、事件流处理

2、各种锁代码案例

Lock
private readonly object _sync = new object();

public void UpdateState()
{
    lock (_sync)
    {
        // 同步操作
    }
}

//高阶实践-Double-check Locking(双重检查锁定)——实现线程安全的单例模式
public sealed class Singleton
{
    private static volatile Singleton _instance;
    private static readonly object _sync = new object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_sync)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }
}

//使用 lock 实现缓存更新同步
public class CacheManager
{
    private Dictionary<string, string> _cache = new Dictionary<string, string>();
    private readonly object _sync = new object();

    public void AddOrUpdate(string key, string value)
    {
        lock (_sync)
        {
            if (_cache.ContainsKey(key))
            {
                _cache[key] = value;
            }
            else
            {
                _cache.Add(key, value);
            }
        }
    }

    public string Get(string key)
    {
        lock (_sync)
        {
            return _cache.TryGetValue(key, out var value) ? value : null;
        }
    }
}
Monitor
Monitor.Enter(_sync);
try
{
    // 同步代码
}
finally
{
    Monitor.Exit(_sync);
}



//高阶用法
//1、带超时的进入锁(TryEnter)
private readonly object _sync = new object();

public bool TryAccess(int timeoutMs)
{
    if (Monitor.TryEnter(_sync, timeoutMs))
    {
        try
        {
            Console.WriteLine("成功获取锁,执行操作...");
            return true;
        }
        finally
        {
            Monitor.Exit(_sync);
        }
    }
    else
    {
        Console.WriteLine("未能在指定时间内获取锁");
        return false;
    }
}
用途: 防止因等待锁而无限阻塞。



// 2、线程间通信:Wait / Pulse

private readonly object _sync = new object();
private bool _dataReady = false;

// 消费者线程
public void Consumer()
{
    Monitor.Enter(_sync);
    try
    {
        while (!_dataReady)
        {
            Console.WriteLine("消费者等待数据...");
            Monitor.Wait(_sync); // 释放锁,等待通知
        }
        Console.WriteLine("数据就绪,开始处理");
    }
    finally
    {
        Monitor.Exit(_sync);
    }
}

// 生产者线程
public void Producer()
{
    Monitor.Enter(_sync);
    try
    {
        Console.WriteLine("生产者正在准备数据...");
        Thread.Sleep(1000); // 模拟耗时操作
        _dataReady = true;
        Monitor.Pulse(_sync); // 唤醒一个等待线程
    }
    finally
    {
        Monitor.Exit(_sync);
    }
}
Wait() 必须放在 while 循环中,防止虚假唤醒。
Pulse() 只唤醒一个线程,PulseAll() 唤醒所有线程。


//自定义细粒度锁控制

private readonly object _sync = new object();
private int _value = 0;

public void UpdateValue(int newValue)
{
    Monitor.Enter(_sync);
    try
    {
        _value = newValue;
        Console.WriteLine($"值已更新为: {_value}");
    }
    finally
    {
        Monitor.Exit(_sync);
    }
}

public int GetValue()
{
    Monitor.Enter(_sync);
    try
    {
        return _value;
    }
    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(3,5);

public async Task AccessResourceAsync()
{
    await _semaphore.WaitAsync();
    try
    {
        // 异步访问资源
    }
    finally
    {
        _semaphore.Release();
    }
}

///异步超时访问(带超时机制)

bool acquired = await _semaphore.WaitAsync(TimeSpan.FromSeconds(2));
if (acquired)
{
    try
    {
        // 成功获得资源
    }
    finally
    {
        _semaphore.Release();
    }
}
else
{
    Console.WriteLine("未能在指定时间内获取资源");
}
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);
}