在C++11之前,C++并没有提供原生的并发支持。开发者通常需要依赖于操作系统的API(如Windows的CreateThread或POSIX的pthread_create)或者第三方库(如Boost.Thread)来创建和管理线程。这些方式存在以下几个问题:
相比之下,C++11的并发库提供了以下优势:
std::thread::join
,C++11会抛出一个std::system_error
异常。std::async
、std::future
和std::promise
等,这些特性使得并发编程更加方便和强大。这些工具使得C++程序员可以更方便、更安全地编写多线程代码。下面我们将详细介绍这些并发工具的使用。
C++11的std::thread
类提供了对操作系统原生线程的封装。你可以通过创建std::thread
对象来创建新的线程,并通过成员函数join()
或detach()
来等待线程结束或让线程在后台运行。
#include <iostream>
#include <thread>
void hello() {
std::cout << "Hello, concurrent world\n";
}
int main() {
std::thread t(hello);
t.join();
}
在这个例子中,我们创建了一个新的线程来运行hello
函数,并在主线程中通过join()
等待新线程结束。
C++11的std::mutex
类提供了对操作系统原生互斥量的封装。你可以使用互斥量来保护共享数据,防止多个线程同时访问。
#include <mutex>
#include <thread>
std::mutex mtx; // 全局互斥量
void print_block(int n, char c) {
mtx.lock();
for (int i=0; i<n; ++i) { std::cout << c; }
std::cout << '\n';
mtx.unlock();
}
int main() {
std::thread th1(print_block,50,'*');
std::thread th2(print_block,50,'$');
th1.join();
th2.join();
return 0;
}
在这个例子中,我们使用互斥量mtx
来保护std::cout
,防止两个线程同时输出。
C++11的std::condition_variable
类提供了对操作系统原生条件变量的封装。你可以使用条件变量来实现线程间的同步。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
}
int main() {
std::thread threads[10];
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_id,i);
std::cout << "10 threads ready to race...\n";
go();
for (auto& th : threads) th.join();
return 0;
}
在这个例子中,我们使用条件变量cv
来实现10个线程的同步。当go
函数被调用时,所有等待在cv
上的线程都会被唤醒。
C++11的std::future
类提供了一种表示异步操作结果的方式。你可以使用std::async
函数来启动一个异步操作,并返回一个std::future
对象。然后你可以在任何时候通过std::future::get
函数来获取异步操作的结果。
#include <iostream>
#include <future>
int factorial(int n) {
int res = 1;
for(int i = n; i > 1; --i)
res *= i;
return res;
}
int main() {
std::future<int> fut = std::async(factorial, 5);
std::cout << "Factorial of 5 is " << fut.get() << std::endl;
return 0;
}
在这个例子中,我们使用std::async
启动了一个异步操作来计算5的阶乘,并通过std::future::get
获取了结果。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。