C++基础 | 线程`std::thread`

什么是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::queuestd::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;
}
相关推荐
sanjiaomao33324 分钟前
从论文公式到Python实现:用单元测试校验滑动平均算法
python·算法·单元测试
Keven_1127 分钟前
算法札记:ACM适用的很骚的C++语法(持续更新)
开发语言·c++
乐迪信息38 分钟前
如何通过AI防爆摄像机精准判断船舶超速?
大数据·人工智能·算法·安全·目标跟踪
mengzhi啊1 小时前
QPluginLoader 动态 DLL 插件版,支持插件之间通信,广播。请求和应答
c++·qt
脉动数据行情11 小时前
C# 实现德指 DAX 期货 WebSocket 实时行情监听
开发语言·websocket·c#
大圣编蚕1 小时前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法
菜鸟~noob2332 小时前
【电子战】第02篇:能量检测器 vs. 相关检测器【含matlab代码】
开发语言·matlab
OpenAnolis小助手2 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
小玮看世界2 小时前
[Python]OD算法在OD实际运用转化参考清单
开发语言·python·算法
黎阳之光3 小时前
数字孪生赋能全域水网,实现水资源管控与节水降碳双向提升
人工智能·物联网·算法·安全·数字孪生