【C++】多线程与并发编程

在这里插入图片描述

上期回顾: 【C++】预处理器与宏及特殊类设计
个人主页:C_GUIQU
归属专栏:C++

在这里插入图片描述

正文

1. 多线程基础

1.1 线程概念

在 C++ 中,线程是程序中独立的执行路径。多线程允许一个程序同时执行多个任务,从而提高程序的效率和响应能力。

1.2 创建线程

在 C++ 11 及以后,可以使用 std::thread 来创建线程。以下是一个简单的示例:

#include <iostream>
#include <thread>

void hello() {
    std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl;
}

int main() {
    std::thread t(hello);
    std::cout << "Hello from main thread " << std::this_thread::get_id() << std::endl;
    t.join();
    return 0;
}

在这个示例中,定义了一个函数 hello,然后通过 std::thread 创建一个新的线程来执行这个函数。在主线程中输出主线程的 ID,新线程中输出新线程的 ID。最后通过 t.join() 等待新线程完成。

2. 线程参数传递

2.1 传递基本数据类型

可以向线程函数传递基本数据类型的参数。例如:

#include <iostream>
#include <thread>

void print_number(int num) {
    std::cout << "Number in thread: " << num << std::endl;
}

int main() {
    int number = 42;
    std::thread t(print_number, number);
    t.join();
    return 0;
}

这里向 print_number 函数传递一个整数参数。

2.2 传递引用类型

当需要在线程函数中修改参数的值时,可以传递引用。但要注意确保引用所指向的对象在整个线程执行期间都有效。

#include <iostream>
#include <thread>

void increment(int& num) {
    num++;
    std::cout << "Incremented number in thread: " << num << std::endl;
}

int main() {
    int number = 10;
    std::thread t(increment, std::ref(number));
    t.join();
    std::cout << "Number in main thread after increment: " << number << std::endl;
    return 0;
}

通过 std::ref 来传递引用,这样在线程中对参数的修改会反映到主线程中的变量。

3. 线程同步

3.1 互斥量(Mutex)

互斥量用于保护共享资源,防止多个线程同时访问。以下是使用 std::mutex 的示例:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mutex_lock;
int shared_variable = 0;

void increment_shared_variable() {
    std::lock_guard<std::mutex> guard(mutex_lock);
    shared_variable++;
}

int main() {
    std::thread t1(increment_shared_variable);
    std::thread t2(increment_shared_variable);
    t1.join();
    t2.join();
    std::cout << "Shared variable value: " << shared_variable << std::endl;
    return 0;
}

这里使用 std::lock_guard 结合 std::mutex 来确保每次只有一个线程能够访问 shared_variable

3.2 条件变量(Condition Variable)

条件变量用于线程间的同步,一个线程等待某个条件满足,另一个线程在条件满足时通知等待的线程。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mutex_lock;
std::condition_variable condition;
bool ready = false;

void waiting_thread() {
    std::unique_lock<std::mutex> lock(mutex_lock);
    condition.wait(lock, [] { return ready; });
    std::cout << "Waiting thread is notified." << std::endl;
}

void signaling_thread() {
    {
        std::lock_guard<std::mutex> guard(mutex_lock);
        ready = true;
    }
    condition.notify_one();
}

int main() {
    std::thread t1(waiting_thread);
    std::thread t2(signaling_thread);
    t1.join();
    t2.join();
    return 0;
}

在这个示例中,waiting_thread 等待条件变量,signaling_thread 在满足条件时通知它。

4. 线程池

4.1 线程池概念

线程池是一种用于管理和复用线程的机制。它包含一组预先创建好的线程,可以接受任务并执行。

4.2 简单线程池实现

以下是一个简单的线程池实现的部分代码:

#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>

class ThreadPool {
public:
    ThreadPool(size_t num_threads) {
        for (size_t i = 0; i < num_threads; ++i) {
            threads.push_back(std::thread(&ThreadPool::worker, this));
        }
    }

    ~ThreadPool() {
        {
            std::lock_guard<std::mutex> guard(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread& th : threads) {
            if (th.joinable()) {
                th.join();
            }
        }
    }

    void enqueue(std::function<void()> task) {
        {
            std::lock_guard<std::mutex> guard(queue_mutex);
            tasks.push(task);
        }
        condition.notify_one();
    }

private:
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> tasks;
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop = false;

    void worker() {
        while (true) {
            std::function<void()> task;
            {
                std::unique_lock<std::mutex> lock(queue_mutex);
                condition.wait(lock, [this] { return stop ||!tasks.empty(); });
                if (stop && tasks.empty()) {
                    return;
                }
                task = tasks.front();
                tasks.pop();
            }
            task();
        }
    }
};

int main() {
    ThreadPool pool(4);
    for (int i = 0; i < 8; ++i) {
        pool.enqueue([i] {
            std::cout << "Task " << i << " is running in thread " << std::this_thread::get_id() << std::endl;
        });
    }
    return 0;
}

这个线程池类创建了指定数量的线程,通过 enqueue 函数可以向线程池添加任务,线程池中的线程会不断从任务队列中获取任务并执行。

结语
感谢您的阅读!期待您的一键三连!欢迎指正!
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Guiat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值