ZoyaPatel

原子操作和互斥锁线程并发方式选择?

SohaniSharma


##C语言 在C语言编程方式,多线程代码编写是一个重要的章节,那么线程同步机制该如何选择呢?本篇文章就是在讨论这个问题。你是在支持无锁Lock Free (原子操作)还是锁实现那一套?{alertInfo}

本文由人工编写审核,非AI生成内容,请放心观看!

{getToc} $title={文章目录}

讨论问题:we have the atomic library, why do we still need mutex and locks?

Mutexes and locks can protect multiple arbitrary data structures with invariants, like complimentary forward and reverse indexes which must be updated together.

They can be used with condition variables to sleep on asynchronous resource availability which doesn’t waste CPU cycles and heat spinning on an atomic variable update.

With spin locks using only atomic operations, programs spend most of their time spinning on contended locks once load gets high enough. This holds even when you mix in scheduler yield calls.

互斥锁(Mutexes)和锁(locks)可以保护多个具有不变性的任意数据结构,比如互补的正向索引和反向索引,它们必须同时更新。

它们可以与条件变量(condition variables)结合使用,以在异步资源可用时进入睡眠状态,从而避免浪费 CPU 循环和因原子变量更新而产生的空转热量。

而使用仅依赖原子操作的自旋锁(spin locks)时,一旦负载足够高,程序大部分时间都会在有争用的锁上空转,即使你在其中混入调度器的让出(scheduler yield)调用,这种情况依然成立。

For one thing, we only have integer atomics (floating point atomics are in C++20). For another, sometimes you need to do things that can’t be achieved with atomics alone. Suppose you need to write stuff into a file from multiple threads. Atomics can’t help you, you have to use a mutex to lock the entire access. STL containers are equally concurrency-unfriendly (writing into one from one thread without locking can actually invalidate iterators held by all other threads, causing any subsequent accesses to result in unpredictable behavior.)

首先,我们只有整数原子操作(浮点原子操作是在 C++20 中才支持的)。

其次,有些事情单靠原子操作是做不到的。比如,你需要从多个线程向同一个文件写入内容。原子操作无能为力,这时候必须使用互斥锁(mutex)来锁住整个访问过程。STL 容器同样对并发不友好(如果在一个线程中不加锁地写入容器,实际上可能会使其他线程持有的迭代器失效,从而导致后续访问出现不可预测的行为)。

Atomic operations allow you to build lockless algorithms but locks are a bit more involved and it's much better to use the system implementation since you don't have to then deal with system specific issues. That makes your code way more portable.

原子操作允许你构建无锁(lockless)算法,但锁(locks)要复杂一些,而且更好的做法是直接使用系统提供的实现,这样你就不用处理系统特定的问题。这会让你的代码更加可移植。

问题二 :无锁编程总是比使用互斥锁更好吗?

暂时没有结论:一般认为上方争论没有结论

但是一般来说,Lock free性能上是更好的。但是不能一概而言

参考视频:https://www.youtube.com/watch?v=ZQFzMfHIxng&ab_channel=CppCon

无锁编程通常用于两个领域:

  • 当你试图将程序扩展到硬件极限时,尽可能提高性能。
  • 你想要互斥锁不提供的特殊属性。 例如:使用大多数无锁编程技术,服务低延迟中断是无等待的。 互斥锁也会使实现并发代码(如中断)变得更加困难。

互斥锁简单、可靠,但会阻塞线程,不适合需要极低延迟或中断响应的场景。

无锁技术提供“特殊属性”:

  • 无阻塞(lock-free / wait-free)
  • 高响应性,适合中断或实时系统
  • 避免优先级反转问题

因此,如果你的目标是处理低延迟中断或高频率并发访问,互斥锁可能不是最优选择。

这里有一篇工程实践的讨论:

结论就是:一般来说,除非你真的知道自己在做什么,否则应该始终使用互斥锁和锁,而不是原子操作。虽然互斥锁速度较慢,但它们本身就足够复杂,而且更容易正确使用。它们会自动处理更改的可见性,因此你的程序更容易理解和编写。

https://stackoverflow.com/questions/55202201/relationship-between-locks-and-atomic-operations-in-thread-programming

总结

为什么要的讨论这个问题、因为,对不同的线程同步机制,很可能极大的影响系统线程并发工作,作为一个系统的核心并发能力是绝对了一个系统核心的性能。

所以:对一个工程师来说,如果你决定优化系统的性能,是否第一时间考虑优化整个系统的并发能力呢?

考虑到实际情况,是否采用何种同步机制,需要用户从自身角度认真考虑,结合实际的情况。

比如:看到论坛的一个说法:无锁编程在 CPU 数量少的时候,程序通常会变慢。无锁算法在可扩展性方面(相对于核心数量)更好。但为了实现这一点,你得付出代价,而你付出的代价就是单线程性能 / 在只有十几个 CPU 左右的机器上的性能(取决于问题和竞争程度)。

各种同步机制

不仅仅是C语言的、消息队列 / Actor 模型 这是一个新语言一般会采取的机制。

1. 互斥锁(Mutex)

  • 最基础的同步机制,保证同一时刻只有一个线程访问共享资源。
  • 用法:
    • 线程 A 获取锁 → 修改数据 → 释放锁 → 线程 B 获取锁
  • 缺点:
    • 线程阻塞等待锁可能导致延迟
    • 容易出现死锁

2. 读写锁(Read-Write Lock)

  • 多线程可以同时读取数据,但写操作独占。
  • 优势:提高读多写少场景的并发效率。

3. 信号量(Semaphore)

  • 控制访问某类资源的线程数量。
  • 分为:
    • 二值信号量(Binary Semaphore):类似互斥锁
    • 计数信号量(Counting Semaphore):控制同时访问资源的线程数量

4. 条件变量(Condition Variable)

  • 线程可以在条件不满足时“睡眠”,等待其他线程通知。
  • 用法:
    • 生产者-消费者模式:生产者生产后通知消费者,消费者消费后通知生产者。

5. 原子操作(Atomic Operation)

  • 单条 CPU 指令就能完成的不可中断操作。
  • 典型操作:
    • atomic incrementCAS (Compare-And-Swap)
  • 优势:
    • 无阻塞(lock-free)
    • 适合高并发场景
  • 缺点:
    • 只能处理简单操作,复杂逻辑难以实现

6. 屏障(Barrier)

  • 用于多线程在某个点同步,所有线程到达后才能继续。

7. 消息队列 / Actor 模型

  • 不共享内存,通过消息传递进行同步。
  • 优势:天然避免锁竞争

同步机制分类

分类 示例 阻塞情况 应用场景
基于锁(Blocking) Mutex、Read-Write Lock、Semaphore 线程可能阻塞 保护共享资源,简单并发场景
无锁 / 原子操作 CAS、Atomic Variable 无阻塞或自旋 高并发、低延迟
条件 / 事件驱动 Condition Variable、Barrier 阻塞等待事件 生产者-消费者、阶段同步
消息传递 / Actor Channel、Queue 非阻塞/异步 避免共享内存,安全并发

来源:

https://www.quora.com/In-C-since-we-have-the-atomic-library-why-do-we-still-need-mutex-and-locks

https://www.youtube.com/watch?v=ZQFzMfHIxng&ab_channel=CppCon

https://www.reddit.com/r/cpp/comments/vg4myt/is_lockfree_programming_is_always_better_than/?tl=zh-hans

 版权声明:感谢您的阅读,资源整理自网络,如果您发现任何侵权行为,请联系 理科生网 管理人员,管理员将及时删除侵权内容。否则均为 理科生网 原创内容,转载时请务必以超链接(而非纯文本链接)标注来源于理科生网及本文完整链接,感谢!{alertInfo}

Ahmedabad
Kolkata
Hyderabad
后一页 Bangalore 前一页

Random Manga

Ads

نموذج الاتصال