Skip to content

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++ 多线程包括:

  1. 多线程的基本概念

    • 线程是操作系统能够进行运算调度的最小单位
    • 用于提高程序的并发性和性能
  2. 创建线程

    • 使用函数创建线程:std::thread t(func);
    • 使用 lambda 表达式创建线程
    • 使用函数对象创建线程
  3. 线程管理

    • join():等待线程结束
    • detach():分离线程
  4. 线程参数

    • 传递参数:std::thread t(func, arg1, arg2);
    • 传递引用参数:std::thread t(func, std::ref(value));
  5. 互斥锁

    • 保护共享资源,防止多个线程同时访问
    • 使用std::mutexstd::lock_guard
  6. 条件变量

    • 用于线程间的同步
    • 使用std::condition_variable
  7. 原子操作

    • 不可分割的操作,不会被线程调度机制打断
    • 使用std::atomic
  8. 线程本地存储

    • 允许每个线程拥有自己的变量副本
    • 使用thread_local

关键概念:

  • 线程:操作系统能够进行运算调度的最小单位
  • join:等待线程结束
  • detach:分离线程
  • 互斥锁:保护共享资源
  • 条件变量:用于线程间的同步
  • 原子操作:不可分割的操作
  • 线程本地存储:每个线程拥有自己的变量副本

掌握多线程是编写高效 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的 Web 编程。