当前位置: 首页 > article >正文

【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 是利器!


http://www.kler.cn/a/612929.html

相关文章:

  • debug 笔记:llama 3.2 部署bug 之cutlassF: no kernel found to launch!
  • 歌词json
  • 【redis】持久化之RDB与AOF
  • [c语言日寄]柔性数组
  • [Java微服务架构]7-3_事务处理——分布式事务
  • UML之包含用例
  • 基于 Qt / HTTP/JSON 的智能天气预报系统测试报告
  • 智慧电力:点亮未来能源世界的钥匙
  • 推荐:大模型靠啥理解文字?通俗解释:词嵌入embedding
  • 网络安全法律法规简介
  • RFID技术在机器人中的核心应用场景及技术实现
  • AI PPT哪家强?2025年4款高效工具深度测评
  • 【数据分享】基于联合国城市化程度框架的全球城市边界数据集(免费获取/Shp格式)
  • 对匿名认证的理解
  • [Java微服务架构]7-2_事务处理——全局事务与共享事务
  • Python每日一题(7)
  • springboot 四层架构之间的关系整理笔记五
  • 怎样进行服务器的日常安全监控和审计?
  • uniapp用户登录及获取用户信息(头像昵称)
  • 全国职业技能大赛_网络安全_中职A模块解析