C++ 之多线程相关总结
C++ 之多线程相关总结
1.多线程相关基础知识
1.1 线程的创建和管理
1. std::thread 类:
用于创建和管理线程。通过将可调用对象(如函数、函数对象、lambda 表达式)作为参数传递给 std::thread
的构造函数,可以创建一个新的线程。
join()
方法会阻塞当前线程,直到被调用的线程执行完毕。如果不调用join()
或detach()
,程序会在std::thread
对象析构时终止程序,因为会调用std::terminate()
。detach()
方法允许线程独立运行,与主线程分离,不再被std::thread
对象管理,它会继续在后台执行直至完成或程序结束。
#include <iostream>
#include <thread>
void threadFunction() {
std::cout << "Thread function running." << std::endl;
}
int main() {
std::thread t(threadFunction); // 创建一个新的线程,执行 threadFunction
t.join(); // 等待线程结束
return 0;
}
2. 线程函数:
可以是普通函数、成员函数、函数对象或 lambda 表达式。
#include <iostream>
#include <thread>
class MyClass {
public:
void memberFunction() {
std::cout << "Member function running in thread." << std::endl;
}
};
int main() {
MyClass obj;
std::thread t(&MyClass::memberFunction, &obj); // 调用成员函数
t.join();
return 0;
}
1.2 线程同步
1.互斥量(Mutex):
- std::mutex 提供了基本的互斥机制,用于保护共享数据,防止多个线程同时访问。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printMessage(const std::string& message) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
std::cout << message << std::endl;
}
int main() {
std::thread t1(printMessage, "Hello from thread 1");
std::thread t2(printMessage, "Hello from thread 2");
t1.join();
t2.join();
return 0;
}
std::lock_guard
是一个 RAII 类,在构造时自动锁定互斥量,在析构时自动解锁,确保正确的锁定和解锁操作。std::unique_lock
提供了更灵活的锁定方式,可以手动加锁、解锁,支持延迟锁定和所有权转移。
2.条件变量(Condition Variables):
- std::condition_variable 允许线程等待某些条件的发生。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;
void producer() {
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::unique_lock<std::mutex> lock(mtx);
dataQueue.push(i);
std::cout << "Produced: " << i << std::endl;
cv.notify_one(); // 通知一个等待的线程
}
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return!dataQueue.empty(); }); // 等待条件满足
int data = dataQueue.front();
dataQueue.pop();
lock.unlock();
std::cout << "Consumed: " << data << std::endl;
if (data == 9) break;
}
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
cv.wait()
会释放锁并等待条件变量被通知,一旦收到通知,它会重新获取锁。
3. 原子操作
std::atomic
模板类提供了原子操作,确保操作的不可分割性,避免数据竞争。
#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 << "Counter value: " << counter << std::endl;
return 0;
}
1.3 线程间通信
1.共享数据:
- 多个线程可以通过共享数据进行通信,但需要使用互斥量或其他同步机制来保护数据。
- 避免死锁,如避免多个线程以不同顺序获取多个锁。
2.消息传递:
- 使用
std::promise
和std::future
可以实现线程间的单向消息传递。
#include <iostream>
#include <thread>
#include <future>
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread t([&prom]() {
int result = factorial(5);
prom.set_value(result);
});
std::cout << "Factorial result: " << fut.get() << std::endl;
t.join();
return 0;
}
1.4 高级线程工具
1. std::async 和 std::future:
std::async
可以异步执行函数,并返回一个std::future
对象。
#include <iostream>
#include <future>
int add(int a, int b) {
return a + b;
}
int main() {
std::future<int> result = std::async(std::launch::async, add, 3, 4);
std::cout << "Sum: " << result.get() << std::endl;
return 0;
}
std::launch::async
表示函数会在另一个线程中立即执行,std::launch::deferred
表示延迟执行,直到调用get()
时才在调用线程中执行。
2. std::packaged_task:
- 包装可调用对象,允许将其作为任务传递,并通过
std::future
获取结果。
#include <iostream>
#include <thread>
#include <future>
int main() {
std::packaged_task<int(int, int)> task(add);
std::future<int> result = task.get_future();
std::thread t(std::move(task), 3, 4);
std::cout << "Sum: " << result.get() << std::endl;
t.join();
return 0;
}
2. 线程的使用:创建及管理
1.类内创建线程
- 可以通过成员函数或者析构函数初始化或者创建线程,通过析构函数关闭/销毁线程
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
class ThreadedClass {
private:
std::thread workerThread;
std::atomic<bool> stopFlag;
// 线程函数
void workerFunction() {
while (!stopFlag) {
std::cout << "Thread is running..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Thread is stopping..." << std::endl;
}
public:
ThreadedClass() : stopFlag(false) {
// 启动线程
workerThread = std::thread(&ThreadedClass::workerFunction, this);
}
~ThreadedClass() {
// 设置停止标志
stopFlag = true;
if (workerThread.joinable()) {
// 等待线程结束
workerThread.join();
}
}
};
int main() {
ThreadedClass obj;
// 让程序运行一段时间,以便观察线程的行为
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
2. 函数内部创建线程
- 单独执行某个函数或者某个类的成员函数
#include <iostream>
#include <thread>
#include <chrono>
class MyClass {
public:
// 类中的函数,将在新线程中执行
void classFunction() {
for (int i = 0; i < 5; ++i) {
std::cout << "Class function running, iteration: " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
};
// 主函数,在其中创建线程执行类的函数
void mainFunction() {
std::cout << "Main function starts." << std::endl;
MyClass obj;
// 创建一个新线程执行类的成员函数
std::thread t(&MyClass::classFunction, &obj);
// 主线程继续执行自己的任务
for (int i = 0; i < 3; ++i) {
std::cout << "Main function running, iteration: " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 等待新线程执行完毕
t.join();
std::cout << "Main function ends." << std::endl;
}
// 函数将在新线程中执行
void newThreadFunction() {
for (int i = 0; i < 5; ++i) {
std::cout << "New thread: " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
mainFunction();
//or
// 创建一个新线程
std::thread newThread(newThreadFunction);
// 主线程继续执行自己的任务
for (int i = 0; i < 3; ++i) {
std::cout << "Main thread: " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 等待新线程执行完成
newThread.join();
return 0;
}
----更新中。。。。。