简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:C++之std::atomic原子bool类型与普通bool区别
2.std::atomic原子bool类型与普通bool区别介绍
-
std::atomic 是 C++11 标准库中的一个模板特化,用于表示一个可以原子操作的布尔值。原子操作意味着这些操作是不可中断的,即在多线程环境中,当一个线程正在执行原子操作时,其他线程无法同时访问或修改这个值。
-
与普通的 bool 类型相比,std::atomic 有以下主要区别和用途:
-
线程安全:普通的 bool 类型不是线程安全的。如果你在多线程环境中共享一个普通的 bool 变量,并且多个线程可能会同时读取或修改它,那么你需要额外的同步机制(如互斥锁)来避免数据竞争和不一致。而 std::atomic 提供了内建的线程安全保证,无需额外的同步。
-
原子操作:你可以对 std::atomic 执行原子操作,如 load(), store(), exchange(), compare_exchange_weak(), 和 compare_exchange_strong()。这些操作在多线程环境中是安全的,因为它们在执行时不会被其他线程打断。相比之下,对普通的 bool 的操作(如赋值或读取)通常不是原子的,因此在多线程环境中可能导致问题。
-
性能:虽然使用 std::atomic 通常比使用互斥锁等同步机制有更高的性能开销,但在某些情况下,它仍然是一个很好的选择。特别是当需要频繁地、快速地访问和修改共享数据时,原子类型可以提供一个相对高效的解决方案,同时保持线程安全。
-
简化的同步:使用 std::atomic 可以简化代码,因为你不需要显式地管理锁或其他同步机制。这可以使代码更易于理解和维护。
-
一个典型的 std::atomic 的使用场景是在多线程环境中作为一个标志位或信号量。例如,一个线程可以原子地设置一个 std::atomic 变量来表示某个任务已经完成,而另一个线程可以原子地检查这个变量来确定是否应该继续执行后续操作。
3.代码实例
<1>.普通bool例子:多线程中的非原子操作(可能导致数据竞争)
#include <iostream>
#include <thread>
#include <chrono> bool ready = false; // 非原子布尔变量 void workerThread() { std::this_thread::sleep_for(std::chrono::seconds(1)); ready = true; // 非原子地设置 ready 为 true
} void waitForSignal() { while (!ready) { std::cout << "Waiting for the signal...\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待信号 } std::cout << "Received the signal!\n";
} int main() { std::thread worker(workerThread); waitForSignal(); worker.join(); return 0;
}
ready 是一个普通的 bool 变量,不是原子的。因此,在多线程环境中对它的读写可能会导致数据竞争和不确定的行为。
<2>.std::atomic例子:线程间的信号通知
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono> std::atomic<bool> ready(false); // 初始化为 false 的原子布尔变量 void workerThread() { std::this_thread::sleep_for(std::chrono::seconds(1)); ready.store(true); // 设置 ready 为 true,通知其他线程 std::cout << "Worker thread finished its work.\n";
} int main() { std::thread t(workerThread); while (!ready.load()) { std::cout << "Waiting for the worker thread to finish...\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待 worker 线程完成 } std::cout << "Main thread detected that the work is ready.\n"; t.join(); return 0;
}
工作线程运行一个循环,直到 running 变量被设置为 false。主线程在一段时间后设置 running 为 false,工作线程检测到这个变化后停止循环。由于 running 是原子的,因此这个检查操作是线程安全的。