C++11 引入了两个重要的同步机制用于多线程编程:std::atomic
和 std::mutex
。它们各自适用于不同的并发控制需求,并在实现和使用上有很大的不同。
std::atomic
:
std::mutex
:
std::atomic
:
std::mutex
更快,因为它利用了硬件提供的原子操作指令,操作开销相对较低。std::mutex
:
std::atomic
:
std::mutex
:
++
操作并不是一个原子操作,该操作分为三步:
load
:将共享变量n从内存加载到寄存器中。update
:更新寄存器里面的值,执行+1操作。store
:将新值从寄存器写回共享变量n的内存地址。多个线程在同一个进程内工作,共享进程的资源,线程本身只拥有线程id、寄存器、线程栈。
因此可能当线程1刚将n的值加载到寄存器中就被切走了,也就是只完成了++
操作的第一步,而线程2可能顺利完成了一次完整的++
操作才被切走,而这时线程1继续用之前加载到寄存器中的值完成剩余的两步操作,最终就会导致两个线程分别对共享变量n进行了一次++
操作,但最终n的值却只被++
了一次。
因此需要加锁或者原子类:
#include #include #include std::atomic atomic_count(0); std::mutex mtx; int count = 0; void atomic_increment() { for (int i = 0; i < 1000; ++i) { atomic_count++; } } void mutex_increment() { for (int i = 0; i < 1000; ++i) { std::lock_guard lock(mtx); count++; } } int main() { std::thread t1(atomic_increment); std::thread t2(atomic_increment); t1.join(); t2.join(); std::cout << "Atomic count: " << atomic_count << std::endl; std::thread t3(mutex_increment); std::thread t4(mutex_increment); t3.join(); t4.join(); std::cout << "Mutex count: " << count << std::endl; return 0; }
std::atomic
:适用于简单的、需要高性能的原子变量操作。例如计数器、单一标志等。std::mutex
:适用于复杂的临界区保护,例如需要保护复杂的数据结构或资源的访问。