Appearance
C++ 多线程
多线程是 C++11 引入的重要特性,它允许程序同时执行多个任务,提高程序的并发性和性能。
1. 多线程的基本概念
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。
1.1 包含头文件
cpp
#include <thread>
#include <iostream>2. 创建线程
2.1 使用函数创建线程
cpp
#include <iostream>
#include <thread>
void func() {
std::cout << "线程正在运行" << std::endl;
}
int main() {
std::thread t(func);
t.join();
return 0;
}2.2 使用 lambda 表达式创建线程
cpp
#include <iostream>
#include <thread>
int main() {
std::thread t([]() {
std::cout << "线程正在运行" << std::endl;
});
t.join();
return 0;
}2.3 使用函数对象创建线程
cpp
#include <iostream>
#include <thread>
class Task {
public:
void operator()() {
std::cout << "线程正在运行" << std::endl;
}
};
int main() {
Task task;
std::thread t(task);
t.join();
return 0;
}3. 线程管理
3.1 join 和 detach
cpp
#include <iostream>
#include <thread>
#include <chrono>
void func() {
std::cout << "线程开始" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "线程结束" << std::endl;
}
int main() {
std::thread t(func);
// 等待线程结束
t.join();
std::cout << "主线程继续" << std::endl;
return 0;
}3.2 detach 示例
cpp
#include <iostream>
#include <thread>
#include <chrono>
void func() {
std::cout << "线程开始" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "线程结束" << std::endl;
}
int main() {
std::thread t(func);
// 分离线程
t.detach();
std::cout << "主线程继续" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}4. 线程参数
4.1 传递参数
cpp
#include <iostream>
#include <thread>
void func(int id, std::string name) {
std::cout << "线程 ID: " << id << ", 姓名: " << name << std::endl;
}
int main() {
std::thread t(func, 1, "张三");
t.join();
return 0;
}4.2 传递引用参数
cpp
#include <iostream>
#include <thread>
void func(int& value) {
value *= 2;
}
int main() {
int value = 10;
std::thread t(func, std::ref(value));
t.join();
std::cout << "value = " << value << std::endl;
return 0;
}5. 互斥锁
互斥锁用于保护共享资源,防止多个线程同时访问。
5.1 基本用法
cpp
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx;
void increment() {
for (int i = 0; i < 100000; i++) {
mtx.lock();
counter++;
mtx.unlock();
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "counter = " << counter << std::endl;
return 0;
}5.2 使用 lock_guard
cpp
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx;
void increment() {
for (int i = 0; i < 100000; i++) {
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "counter = " << counter << std::endl;
return 0;
}6. 条件变量
条件变量用于线程间的同步,允许一个线程等待另一个线程的通知。
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; });
std::cout << "线程被唤醒" << std::endl;
}
int main() {
std::thread t(worker);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
t.join();
return 0;
}7. 原子操作
原子操作是不可分割的操作,不会被线程调度机制打断。
cpp
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> counter(0);
void increment() {
for (int i = 0; i < 100000; i++) {
counter++;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "counter = " << counter << std::endl;
return 0;
}8. 线程本地存储
线程本地存储(Thread Local Storage, TLS)允许每个线程拥有自己的变量副本。
cpp
#include <iostream>
#include <thread>
#include <mutex>
thread_local int value = 0;
std::mutex mtx;
void func(int id) {
value = id;
std::lock_guard<std::mutex> lock(mtx);
std::cout << "线程 " << id << " 的 value = " << value << std::endl;
}
int main() {
std::thread t1(func, 1);
std::thread t2(func, 2);
std::thread t3(func, 3);
t1.join();
t2.join();
t3.join();
return 0;
}9. 示例:生产者-消费者模型
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::queue<int> buffer;
const unsigned int max_size = 10;
std::mutex mtx;
std::condition_variable cv_producer;
std::condition_variable cv_consumer;
void producer(int id) {
for (int i = 0; i < 20; i++) {
std::unique_lock<std::mutex> lock(mtx);
cv_producer.wait(lock, []{ return buffer.size() < max_size; });
buffer.push(i);
std::cout << "生产者 " << id << " 生产了 " << i << std::endl;
cv_consumer.notify_one();
}
}
void consumer(int id) {
for (int i = 0; i < 20; i++) {
std::unique_lock<std::mutex> lock(mtx);
cv_consumer.wait(lock, []{ return !buffer.empty(); });
int value = buffer.front();
buffer.pop();
std::cout << "消费者 " << id << " 消费了 " << value << std::endl;
cv_producer.notify_one();
}
}
int main() {
std::thread p1(producer, 1);
std::thread p2(producer, 2);
std::thread c1(consumer, 1);
std::thread c2(consumer, 2);
p1.join();
p2.join();
c1.join();
c2.join();
return 0;
}小结
C++ 多线程包括:
多线程的基本概念:
- 线程是操作系统能够进行运算调度的最小单位
- 用于提高程序的并发性和性能
创建线程:
- 使用函数创建线程:
std::thread t(func); - 使用 lambda 表达式创建线程
- 使用函数对象创建线程
- 使用函数创建线程:
线程管理:
join():等待线程结束detach():分离线程
线程参数:
- 传递参数:
std::thread t(func, arg1, arg2); - 传递引用参数:
std::thread t(func, std::ref(value));
- 传递参数:
互斥锁:
- 保护共享资源,防止多个线程同时访问
- 使用
std::mutex和std::lock_guard
条件变量:
- 用于线程间的同步
- 使用
std::condition_variable
原子操作:
- 不可分割的操作,不会被线程调度机制打断
- 使用
std::atomic
线程本地存储:
- 允许每个线程拥有自己的变量副本
- 使用
thread_local
关键概念:
- 线程:操作系统能够进行运算调度的最小单位
- join:等待线程结束
- detach:分离线程
- 互斥锁:保护共享资源
- 条件变量:用于线程间的同步
- 原子操作:不可分割的操作
- 线程本地存储:每个线程拥有自己的变量副本
掌握多线程是编写高效 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的 Web 编程。