什么是std::thread
?
std::thread
是C++11中引入的一个类,用于表示和管理线程。通过std::thread
,我们可以创建一个新的线程来执行指定的任务。线程是操作系统调度的基本单位,多个线程可以并发执行,从而提高程序的效率。
创建线程
基本用法
要创建一个线程,只需实例化一个std::thread
对象,并传入一个可调用对象(如函数、Lambda表达式或函数对象)作为参数。
cpp
#include <iostream>
#include <thread>
void hello() {
std::cout << "Hello from thread!\n";
}
int main() {
std::thread t(hello); // 创建一个线程,执行hello函数
t.join(); // 等待线程结束
return 0;
}
在这个示例中,我们创建了一个线程t
,它执行hello
函数。join()
方法用于等待线程执行完毕。
使用Lambda表达式
我们也可以使用Lambda表达式来创建线程。
cpp
#include <iostream>
#include <thread>
int main() {
std::thread t([]() {
std::cout << "Hello from Lambda thread!\n";
});
t.join();
return 0;
}
带参数的线程函数
线程函数可以接受参数,只需在创建线程时传递相应的参数即可。
cpp
#include <iostream>
#include <thread>
void print_message(const std::string& message) {
std::cout << message << '\n';
}
int main() {
std::thread t(print_message, "Hello from thread with arguments!");
t.join();
return 0;
}
线程的管理
join()
与detach()
join()
:等待线程执行完毕。调用join()
后,主线程会阻塞,直到子线程完成。detach()
:将线程与std::thread
对象分离,线程在后台独立运行。分离后的线程不能再被join()
。
cpp
#include <iostream>
#include <thread>
#include <chrono>
void task() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Task completed!\n";
}
int main() {
std::thread t(task);
t.detach(); // 分离线程
std::cout << "Main thread continues...\n";
std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待子线程完成
return 0;
}
线程的移动语义
std::thread
支持移动语义,可以将一个线程的所有权从一个std::thread
对象转移到另一个。
cpp
#include <iostream>
#include <thread>
void task() {
std::cout << "Task executed!\n";
}
int main() {
std::thread t1(task);
std::thread t2 = std::move(t1); // 将t1的所有权转移给t2
t2.join();
return 0;
}
线程同步
多线程编程中,线程之间的共享资源可能会导致数据竞争问题。为了解决这个问题,C++提供了多种同步机制,如互斥锁(std::mutex
)和条件变量(std::condition_variable
)。
使用std::mutex
std::mutex
用于保护共享资源,确保同一时间只有一个线程可以访问该资源。
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex mtx;
int shared_data = 0;
void increment() {
for (int i = 0; i < 10000; ++i) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
++shared_data;
}
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back(increment);
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final value of shared_data: " << shared_data << '\n'; // 输出:100000
return 0;
}
使用std::condition_variable
std::condition_variable
用于线程间的通信,允许线程等待某些条件成立。
cpp
#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> lock(mtx);
cv.wait(lock, []() { return ready; }); // 等待条件成立
std::cout << "Thread " << id << " is running!\n";
}
int main() {
std::thread threads[10];
for (int i = 0; i < 10; ++i) {
threads[i] = std::thread(print_id, i);
}
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true; // 设置条件为true
}
cv.notify_all(); // 通知所有等待的线程
for (auto& t : threads) {
t.join();
}
return 0;
}
线程池的实现
虽然C++标准库没有直接提供线程池,但我们可以使用std::thread
和其他工具(如std::queue
和std::function
)来实现一个简单的线程池。
cpp
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
class ThreadPool {
public:
ThreadPool(size_t num_threads) {
for (size_t i = 0; i < num_threads; ++i) {
workers.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
if (this->stop && this->tasks.empty()) {
return;
}
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
});
}
}
template <class F>
void enqueue(F&& f) {
{
std::unique_lock<std::mutex> lock(queue_mutex);
tasks.emplace(std::forward<F>(f));
}
condition.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread& worker : workers) {
worker.join();
}
}
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop = false;
};
int main() {
ThreadPool pool(4);
for (int i = 0; i < 8; ++i) {
pool.enqueue([i] {
std::cout << "Task " << i << " is running on thread " << std::this_thread::get_id() << '\n';
std::this_thread::sleep_for(std::chrono::seconds(1));
});
}
return 0;
}