目录
std::lock_guard 和 std::unique_lock 的使用
条件变量(std::condition_variable)的应用
一,并发编程的背景和挑战
随着多核处理器的普及,程序设计逐渐向并发计算转变。并发编程的目标是通过同时执行多个任务,提高程序的执行效率,充分利用现代硬件的计算能力。然而,随着程序复杂性的增加,并发编程面临许多挑战。常见的问题包括数据竞争、死锁、线程调度、负载不均等。
C++作为一种性能极高的编程语言,自C++11以来,逐步增强了并发支持,提供了许多工具和库,帮助我们在多核环境下高效编程。但即便如此,并发编程的复杂性依然存在。
1,并发编程中的常见问题
在并发编程中,最常见的挑战是数据竞争、死锁、活锁和资源争用等问题:
- 数据竞争:多个线程访问共享资源,并且至少有一个线程尝试写入资源时,若没有适当的同步机制,可能会发生数据竞争,导致程序行为不可预期。
- 死锁:两个或多个线程在持有资源锁时,互相等待对方释放资源,形成循环等待,最终导致程序停滞。
- 活锁:线程之间相互响应,导致所有线程都无法继续执行,即使没有发生死锁。
- 资源争用:多个线程同时竞争同一个资源,可能导致线程的执行效率下降,甚至发生“饥饿”现象。
2,C++ 在并发编程中的优势与挑战
C++ 在并发编程方面的最大优势在于其高性能和对底层硬件的直接控制,尤其是在需要进行高效计算的领域(如图像处理、科学计算等)具有独特的优势。然而,这也意味着 C++ 并发编程相较于一些更高层次的语言更为复杂,需要我们精心管理内存、同步机制和线程生命周期等。
二,C++并发编程的基础
1,C++11 引入的并发支持
C++11 引入了诸多并发编程相关的新特性,使得并发编程变得更加简便和安全。
线程(std::thread
)的基础使用
C++11 引入了 std::thread
类,它提供了一种管理线程的简单方式。创建线程时,直接传入要执行的函数或可调用对象。
#include <iostream>
#include <thread>
void print_hello() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(print_hello);
t.join(); // 等待线程执行完毕
return 0;
}
std::mutex
与互斥锁
std::mutex
用于在多个线程之间保护共享资源,防止数据竞争。通过 lock()
和 unlock()
方法,我们可以在临界区内对资源进行保护。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_numbers(int id) {
mtx.lock();
std::cout << "Thread " << id << " is printing a number." << std::endl;
mtx.unlock();
}
int main() {
std::thread t1(print_numbers, 1);
std::thread t2(print_numbers, 2);
t1.join();
t2.join();
return 0;
}
std::lock_guard
和 std::unique_lock
的使用
为了避免手动调用 lock()
和 unlock()
,我们可以使用 std::lock_guard
和 std::unique_lock
。它们采用 RAII(资源获取即初始化)模式,在作用域结束时自动释放锁,确保锁的正确释放。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_numbers(int id) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁与释放锁
std::cout << "Thread " << id << " is printing a number." << std::endl;
}
int main() {
std::thread t1(print_numbers, 1);
std::thread t2(print_numbers, 2);
t1.join();
t2.join();
return 0;
}
条件变量(std::condition_variable
)的应用
条件变量用于线程间的同步,它可以让一个线程等待某个条件的发生,并允许其他线程在条件满足时通知它。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_numbers() {
std::unique_lock<std::mutex> lock(mtx);
while (!ready) cv.wait(lock); // 等待条件满足
std::cout << "Numbers printed." << std::endl;
}
void set_ready() {
std::unique_lock<std::mutex> lock(mtx);
ready = true;
cv.notify_all(); // 通知所有等待线程
}
int main() {
std::thread t1(print_numbers