C++关键段、原子锁、互斥量及信号量的实现和区别

本文介绍了C++中多线程编程的关键概念,包括关键段、原子锁、互斥量和信号量。重点讨论了原子锁在改变变量值时的便利性,以及互斥量和信号量的区别——互斥量用于线程互斥,确保资源访问的唯一性,而信号量则用于线程同步,控制资源的有序访问。

1.关键段

CRITICAL_SECTION m_cs; //创建一个关键段
InitializeCriticalSection(&m_cs);  //初始化关键段

EnterCriticalSection(&pthis->m_cs);
//此处是需要互斥进入的代码段
LeaveCriticalSection(&pthis->m_cs);

DeleteCriticalSection(&m_cs);  //删除关键段

2.原子锁

一般情况下,在多线程编程中如果对某一个变量的值进行改变的话,使用原子锁比较方便

InterlockedIncrement(&pthis->m_lRunThreadNum); //加1操作
//...
InterlockedDecrement(&pthis->m_lRunThreadNum); //减1操作

3.互斥量

2.信号量

注意:互斥量用于线程的互斥,信号量用于线程的同步。

这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。

互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源

内存屏障与互斥锁、信号量在概念、作用使用场景等方面存在区别。 ### 概念方面 - **内存屏障**:并非锁,是保证内存操作顺序的一种机制。锁使用汇编原语如 LOCK、UNLOCK 等,这些是内存屏障的隐式形式,内存屏障是锁实现同步功能的基础之一,几乎所有的锁都使用了内存屏障来保证操作的顺序性可见性[^2]。 - **互斥锁**:是一种用户层的同步处理方式,用于保护临界区,确保同一时间只有一个线程能进入临界区执行操作,其语义明确,即“同一时间只允许一个线程进入”[^1]。 - **信号量**:可以通过初始值设为 1 模拟互斥锁的功能,但它本质上是一个计数器,用于控制对共享资源的访问数,其值表示可用资源的数。 ### 作用方面 - **内存屏障**:主要作用是保证内存操作的顺序,避免编译器处理器对指令进行重排序,确保数据的可见性,使不同线程对内存的读写操作按照预期的顺序执行。 - **互斥锁**:重点在于保护临界区,防止多个线程同时访问共享资源而产生数据竞争问题,确保共享资源的一致性完整性。 - **信号量**:用于控制多个线程对有限资源的访问,当资源数大于 1 时,信号量可以允许多个线程同时访问资源,而互斥锁只能允许一个线程访问。 ### 使用场景方面 - **内存屏障**:在多线程编程中,当需要确保特定的内存操作顺序时使用,例如在实现锁、原子操作等同步机制时,或者在处理硬件设备的内存映射时。 - **互斥锁**:适用于保护临界区,当多个线程需要访问同一共享资源,且该资源在同一时间只能被一个线程访问时,使用互斥锁是更自然的选择,其语义清晰,能避免代码逻辑的混乱[^1]。 - **信号量**:除了可以模拟互斥锁的功能外,更适用于控制对多个相同资源的并发访问,例如多个线程需要访问多个相同的文件描述符、网络连接等情况。 ### 代码示例 #### 内存屏障(以 C++ 为例) ```cpp #include <atomic> std::atomic<int> x, y; void thread1() { x.store(1, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_release); y.store(1, std::memory_order_relaxed); } void thread2() { while (y.load(std::memory_order_relaxed) == 0) ; std::atomic_thread_fence(std::memory_order_acquire); int r1 = x.load(std::memory_order_relaxed); } ``` #### 互斥锁(以 Python 为例) ```python import threading mutex = threading.Lock() shared_variable = 0 def increment(): global shared_variable mutex.acquire() try: shared_variable += 1 finally: mutex.release() threads = [] for _ in range(10): t = threading.Thread(target=increment) threads.append(t) t.start() for t in threads: t.join() print(shared_variable) ``` #### 信号量(以 Java 为例) ```java import java.util.concurrent.Semaphore; public class SemaphoreExample { private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " acquired the semaphore"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + " released the semaphore"); } }).start(); } } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值