C++ 线程池

19 阅读2分钟

线程安全: 如果多线程程序每次运行结果和单线程运行的结果一致,那么线程就是安全的

#include <thread>

void test(const string &msg)
{
    std::cout << msg << std::endl;
}
int mian()
{
    //创建线程
    std::thread thread1(test, "hello");
    bool isJoin = thread1.joinable();
    if(isJoin)
    {
        thread1.join();//主线程在这里等待子线程结束
    }
    
    //thread1.detach();//子线程在后台执行
}

`std::thread`的`joinable()`函数返回`false`的情况有以下几种:

1.  **默认构造的线程对象**:即没有关联任何线程执行函数。
2.  **已经被移动的线程对象**:线程对象的所有权已经被转移给另一个线程对象。
3.  **已经被`join`的线程**:线程已经调用过`join()`,此时线程已经执行完毕,并且资源已经被清理。
4.  **已经被`detach`的线程**:线程已经调用过`detach()`,线程与线程对象分离,独立运行。

锁:

#include <thread>
#include <mutex>
int shared_data = 0;
std::mutex mtx;
std::timed_mutex mtx;
void func()
{
    for(int i = 0; i < 10; i++)
    {
        //mtx.lock();第一种方法
        //std::lock_guard<std::mutex> lg(mtx);第二种方法
        //std::unique_lock<std::mutex> lg(mtx);第三种方法
        shared_data++;
        //mtx.unlock();第一种方法
        
        //还有一种是timed_mutex,可以指定等待锁的时间
    }
}
int main()
{
    std::thread t1(func);
    std::thread t2(func);
    t1.join();
    t2.join();
    std::cout << shared_data << std::endl;
    return 0;
}

生产消费者 image.png

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

std::queue<int> g_queue;
std::condition_variable g_cv;
std::mutex mtx;
void Producer() //生产者
{
    for(int i = 0; i < 10;i++)
    {
        std::unique_lock<std::mutex> lock(mtx);
        g_queue.push(i);
        //通知消费者
        g_cv.notify_one();
    }   
}
 void Consumer()
 {
     while(1)
     {
         std::unique_lock<std::mutex> lock(mtx);
         //bool isempty = g_queue.empty();
        // g_cv.wait(lock, !isempty);
         g_cv.wait(lock, ()[]{return !g_queue.empty()});
         int vaule = g_queue.front();
         g_queue.pop();
     }
 }
int main()
{
    std::thread t1(Producer);
    std::thread t1(Consumer);
    t1.join();
    t2.join();
    return 0;
}

线程池

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

class ThreadPool{
public:
    ThreadPool(int numThreads):stop(false)
    {
        for(int i=0;i < numThreads; i++)
        {
            thread.emplace_back([this]{
            while(1){
                std::unique_lock<std::mutex> lock(mtx);
                condition.wait(lock,[this]{return !task.empty() || stop});
                if (stop && tasks.empty())
                {
                    return;
                }
                std::function<void()> task(std::move(tasks.front()));
                tasks.pop();
                lock.unlock();
                task();
                
            }
            })
        }
    }
    ~ThreadPool()
    {
        std::unique_lock<std::mutex> lock(mtx);
        stop = true;
        condition.notify_all();
        for(auto& t : threads)
        {
            t.join();
        }
    }
    
    template<class F,class... Args>
    void enqueue(F &&f, Args&&... args)
    {
        std::function<void()> task = 
            std::bind(std::forward<F>(f), std::forward<Args>((args)...));
        std::unique_lock<std::mutex> lock(mtx);
        tasks.emplace(std::move(task));
        condition.notify_one();
    }
private:
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> tasks;
    std::mutex mtx;
    std::condition_variable condition;
    bool stop;
};