jiegemena Blog

哪些事情,我相信!

c++多线程

在C++中,多线程编程是实现并发和并行处理的重要方式。C++11引入了标准的多线程支持,使得多线程编程更加简洁和安全。以下是一些关于C++多线程的关键内容和示例代码。

1. 线程的创建

C++11引入了std::thread类,用于创建和管理线程。

示例代码:

#include <iostream>
#include <thread>

void threadFunction(int num) {
    std::cout << "Thread " << num << " is running." << std::endl;
}

int main() {
    std::thread t1(threadFunction, 1); // 创建线程t1
    std::thread t2(threadFunction, 2); // 创建线程t2

    t1.join(); // 等待线程t1完成
    t2.join(); // 等待线程t2完成

    std::cout << "Main thread is done." << std::endl;
    return 0;
}

2. 线程的同步

多线程编程中,线程同步是关键。C++提供了多种同步机制,如互斥锁(std::mutex)、条件变量(std::condition_variable)、锁(std::lock_guardstd::unique_lock)等。

示例代码:使用互斥锁

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

std::mutex mtx; // 互斥锁

void printBlock(int n, char c) {
    std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
    for (int i = 0; i < n; ++i) {
        std::cout << c;
    }
    std::cout << '\n';
}

int main() {
    std::thread t1(printBlock, 50, '*');
    std::thread t2(printBlock, 50, '$');

    t1.join();
    t2.join();

    return 0;
}

3. 线程池

线程池是一种常用的并发模式,用于管理线程的创建和销毁,避免频繁创建和销毁线程带来的开销。

示例代码:简单的线程池

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

class ThreadPool {
public:
    ThreadPool(size_t numThreads) {
        for (size_t i = 0; i < numThreads; ++i) {
            workers.emplace_back(
                [this] {
                    while (true) {
                        std::function<void()> task;
                        {
                            std::unique_lock<std::mutex> lock(queueMutex);
                            condition.wait(lock, [this] { return stop || !tasks.empty(); });
                            if (stop && tasks.empty()) return;
                            task = std::move(tasks.front());
                            tasks.pop();
                        }
                        task();
                    }
                }
            );
        }
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread &worker : workers) {
            worker.join();
        }
    }

    template <class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );

        std::future<return_type> res = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
            tasks.emplace([task]() { (*task)(); });
        }
        condition.notify_one();
        return res;
    }

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

int main() {
    ThreadPool pool(4);

    auto result1 = pool.enqueue([](int answer) { return answer; }, 42);
    auto result2 = pool.enqueue([](int answer) { return answer; }, 43);

    std::cout << "Result 1: " << result1.get() << std::endl;
    std::cout << "Result 2: " << result2.get() << std::endl;

    return 0;
}

4. 线程安全的队列

线程安全的队列是多线程编程中常用的工具,用于在多个线程之间安全地传递数据。

示例代码:线程安全的队列

#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>

template <typename T>
class ThreadSafeQueue {
private:
    std::queue<T> queue;
    std::mutex mtx;
    std::condition_variable cv;
    bool done = false;

public:
    ThreadSafeQueue() = default;
    ThreadSafeQueue(const ThreadSafeQueue&) = delete;
    ThreadSafeQueue& operator=(const ThreadSafeQueue&) = delete;

    void push(T value) {
        std::lock_guard<std::mutex> lock(mtx);
        queue.push(std::move(value));
        cv.notify_one();
    }

    T pop() {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [this] { return !queue.empty() || done; });
        if (queue.empty()) throw std::runtime_error("No more elements");
        T tmp = std::move(queue.front());
        queue.pop();
        return tmp;
    }

    void stop() {
        std::unique_lock<std::mutex> lock(mtx);
        done = true;
        cv.notify_all();
    }

    bool empty() const {
        std::lock_guard<std::mutex> lock(mtx);
        return queue.empty();
    }
};

int main() {
    ThreadSafeQueue<int> queue;

    std::thread producer([&queue] {
        for (int i = 0; i < 10; ++i) {
            queue.push(i);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        queue.stop();
    });

    std::thread consumer([&queue] {
        while (true) {
            try {
                int value = queue.pop();
                std::cout << "Consumed: " << value << std::endl;
            } catch (const std::runtime_error& e) {
                std::cout << e.what() << std::endl;
                break;
            }
        }
    });

    producer.join();
    consumer.join();

    return 0;
}

5. 线程的性能优化

在多线程编程中,性能优化是一个重要的方面。以下是一些常见的优化技巧:

  • 减少锁的使用:尽量减少锁的使用范围,避免锁的过度竞争。
  • 使用无锁编程:在某些情况下,可以使用无锁数据结构来提高性能。
  • 合理分配线程:根据系统的CPU核心数合理分配线程数量,避免过多线程导致的上下文切换开销。

6. 线程的异常处理

在多线程编程中,异常处理是一个重要的问题。C++11提供了std::futurestd::promise来支持线程间的异常传递。

示例代码:线程异常处理

#include <iostream>
#include <thread>
#include <future>
#include <exception>

int main() {
    std::promise<int> result;
    std::future<int> future = result.get_future();

    std::thread worker([&result] {
        try {
            throw std::runtime_error("Something went wrong");
        } catch (...) {
            result.set_exception(std::current_exception());
        }
    });

    try {
        std::cout << "The answer is (should be exception): " << future.get() << std::endl;
    } catch (std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }

    worker.join();
    return 0;
}

7. 线程的资源管理

在多线程编程中,资源管理是一个重要的问题。C++11提供了std::shared_ptrstd::unique_ptr来支持线程间的资源管理。

示例代码:线程资源管理

#include <iostream>
#include <thread>
#include <memory>

void worker(std::shared_ptr<int> ptr) {
    std::cout << "Worker thread: " << *ptr << std::endl;
}

int main() {
    std::shared_ptr<int> ptr = std::make_shared<int>(42);
    std::thread t(worker, ptr);

    std::cout << "Main thread: " << *ptr << std::endl;

    t.join();
    return 0;
}