【C#】`Interlocked` vs `lock`

Interlockedlock 是 C# 中常用的两种线程同步机制,但它们用途不同、性能差距大。下面我们来详细对比一下:


🆚 Interlocked vs lock 对比一览

项目Interlockedlock
🧠 本质原子操作指令(CPU级别)加锁机制(线程阻塞)
🚀 性能极高(轻量,适合频繁调用)相对较低(阻塞线程)
✅ 原子性✅ 支持✅ 支持
✅ 可见性✅ 有效✅ 有效
✅ 线程安全✅ 是✅ 是
⚠️ 可操作范围仅限数值或引用操作可以包住任何代码块
🛠 使用复杂度简单,但受限灵活,控制力强
🚫 可重入性无需考虑需要注意死锁、递归
🔄 阻塞不阻塞线程会阻塞其他线程直到释放锁

📌 什么时候用 Interlocked

适合非常简单的并发修改操作,如:

  • 计数器递增
  • 设置引用对象
  • 比较交换值(CAS)

🔧 示例:线程安全地计数

private int counter = 0;

public void Increment()
{
    Interlocked.Increment(ref counter);
}

这是线程安全的,因为 Interlocked.Increment 是原子操作,在底层是汇编指令,不需要锁。


📌 什么时候用 lock

适合多个操作需要作为一个整体执行,或者操作逻辑较复杂,比如:

  • 修改多个字段
  • 需要包含条件判断
  • 涉及复杂流程逻辑

🔧 示例:线程安全地修改共享对象

private object _lockObj = new object();
private List<string> list = new List<string>();

public void AddItem(string item)
{
    lock (_lockObj)
    {
        if (!list.Contains(item))
        {
            list.Add(item);
        }
    }
}

✅ 举个实际例子对比:

比如你要实现一个线程安全的 ID 生成器:

Interlocked

private int _nextId = 0;
public int GetNextId()
{
    return Interlocked.Increment(ref _nextId);
}

如果用 lock 也可以:

private object _lock = new object();
private int _nextId = 0;

public int GetNextId()
{
    lock (_lock)
    {
        return ++_nextId;
    }
}

效果一样,但 Interlocked 的性能更高,尤其在高并发下。


🧠 总结一句话:

如果你只是修改一个变量,优先用 Interlocked,性能更高;
如果你要操作多个变量或执行复杂逻辑,就用 lock,更通用更灵活。


你这个相机采集系统如果涉及采图计数、图像编号、控制状态这些,可以大量使用 Interlocked;如果是控制图像队列、处理流程,就可能需要 lock

Interlocked其他操作

🎯 Interlocked 不只是递增,它支持多种原子操作,只要是对整数或引用的线程安全操作,Interlocked 几乎都有对应的方法。

下面是它的几种常用操作:


✅ 常用 Interlocked 操作一览

方法名说明示例
Increment(ref int)原子递增 +1Interlocked.Increment(ref counter);
Decrement(ref int)原子递减 -1Interlocked.Decrement(ref counter);
Add(ref int, value)原子加任意数Interlocked.Add(ref total, 5);
Exchange(ref T, value)原子替换值(赋新值,返回旧值)Interlocked.Exchange(ref flag, 1);
CompareExchange(ref T, newValue, expected)原子比较并替换(CAS)Interlocked.CompareExchange(ref flag, 1, 0);

🔍 举几个实用例子

🔢 原子加减任意值

int total = 0;
Interlocked.Add(ref total, 10);    // 加 10
Interlocked.Add(ref total, -3);    // 减 3

🔄 原子交换值(Exchange)

适用于原子性“状态切换”:

int isProcessing = 0;

// 尝试设置为“处理中”
if (Interlocked.Exchange(ref isProcessing, 1) == 0)
{
    // 成功设置为处理状态
    DoWork();
    // 处理完成,重置
    Interlocked.Exchange(ref isProcessing, 0);
}

💣 原子“只有一个线程能进来”:CompareExchange(CAS)

int started = 0;

if (Interlocked.CompareExchange(ref started, 1, 0) == 0)
{
    // 只有第一次会进来
    Console.WriteLine("Only one thread can enter here.");
}

解释:

  • 如果当前值是 0,就设置为 1,表示“我抢到了锁”
  • 返回原值(如果不是 0 就说明别人先抢到了)

🧠 总结一句话:

Interlocked 是一个线程安全的整数和引用操作工具类,不仅能递增递减,还能实现原子加法、值替换、CAS 等,高性能、无锁,非常适合并发场景


如果你在做一些并发计数器、控制标志位、实现轻量锁,Interlocked 是利器!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code bean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值