C++ 作为一种成熟的编程语言,早在 C++11 标准就引入了不少并发编程机制,以满足现代软件开发对高效与并发计算的需求。从此之后,C++ 标准库不断扩展并发特性,使得开发者能够更容易地编写多线程程序。本文将深入探讨 C++ 框架内置的主要并发控制机制,包括线程、互斥量、条件变量、原子操作和任务并行库等。
线程
线程在几乎所有并发编程中都是一个核心概念。C++11 标准库引入了 std::thread
类,使得创建和管理线程更加方便。
创建线程
创建一个新线程只需要简单地实例化 std::thread
对象,并传递一个可调用对象作为参数:
#include <iostream>
#include <thread>
void task() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(task);
t.join(); // 等待线程结束
return 0;
}
线程同步
必须注意多个线程对共享资源的访问可能会引起资源竞争,导致数据不一致或程序崩溃。C++ 提供了多种同步机制来解决这些问题。
互斥量
互斥锁(Mutex)是最常用的同步原语之一,它可以确保共享资源在同一时间只能被一个线程修改。C++ 标准库提供了 std::mutex
类来实现互斥锁。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_message(const std::string& message) {
std::lock_guard<std::mutex> lock(mtx);
std::cout << message << std::endl;
}
int main() {
std::thread t1(print_message, "Hello from thread 1");
std::thread t2(print_message, "Hello from thread 2");
t1.join();
t2.join();
return 0;
}
条件变量
条件变量提供了一种线程间的通信机制。一个线程可以等待某个条件发生,而另一个线程则负责通知条件的变化。C++ 标准库通过 std::condition_variable
提供了条件变量支持。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void wait_for_ready() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; });
std::cout << "Thread notified!" << std::endl;
}
void set_ready() {
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_all();
}
int main() {
std::thread t1(wait_for_ready);
std::thread t2(set_ready);
t1.join();
t2.join();
return 0;
}
原子操作
对于一些简单的同步任务,使用锁较为笨重且效率不高。C++11 引入了 std::atomic
模板类,提供了一种无锁(lock-free)的方式来实现原子操作。
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
++counter;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final counter value: " << counter << std::endl;
return 0;
}
任务并行库
C++11 还引入了 std::async
和 std::future
,这些机制支持任务级别的并行,简化了并发任务的管理。
std::async
std::async
允许我们启动一个异步任务,并获取其结果:
#include <iostream>
#include <future>
int sum(int a, int b) {
return a + b;
}
int main() {
std::future<int> result = std::async(sum, 10, 20);
std::cout << "Sum is: " << result.get() << std::endl;
return 0;
}
std::future
std::future
对象用来存储异步操作的结果,并提供一种机制来检查其状态或等待结果完成。
#include <iostream>
#include <future>
void print_message(const std::string& message, std::promise<std::string> result) {
std::this_thread::sleep_for(std::chrono::seconds(1));
result.set_value(message);
}
int main() {
std::promise<std::string> promise;
std::future<std::string> future = promise.get_future();
std::thread t(print_message, "Hello from async task", std::move(promise));
std::cout << future.get() << std::endl;
t.join();
return 0;
}
总之,C++ 为并发编程提供了丰富的内置机制,从低级的线程和同步原语,到高级的任务并行库,这些工具可以帮助开发者更高效地利用多核处理器,实现复杂的并发任务。