Kwo0D 2021-10-18 13:05 采纳率: 0%
浏览 37
已结题

为什么这个线程池有时候会double free?


#include<pthread.h>
#include<unistd.h>
#include<list>
#include<stdio.h>
#include<vector>
#include<list>
static int i = 0;

class Lock{
    public:
        Lock() {
            pthread_mutex_init(&lock_, NULL);
        }
        ~Lock() {
            pthread_mutex_unlock(&lock_);
        }
        void lock() {
            pthread_mutex_lock(&lock_);
        }
        void unlock() {
            pthread_mutex_unlock(&lock_);
        }
    private:
        pthread_mutex_t lock_;
};

class Sem{
    public:
        Sem() {
            pthread_cond_init(&cond_, NULL);
        }
        ~Sem() {
            pthread_cond_broadcast(&cond_);
        }
        void wait() {
            pthread_cond_wait(&cond_, &lock_);
        }
        void post() {
            pthread_cond_signal(&cond_);
        }
    private:
        pthread_mutex_t lock_;
        pthread_cond_t cond_;
};

template <typename T>
class ThreadPool {
    public:
        ThreadPool(int thd_num = 8, int max_req = 10000);
        ~ThreadPool();

        bool append(T* request);
    private:
        static void* worker(void* args);
        void run();
        int max_threads_number_;
        int max_requests_number_;
        std::vector<pthread_t> threads_;
        std::list<T*> works_;
        Lock lock_;
        Sem sem_;
        bool stop_;
};
template <typename T> 
ThreadPool<T>::ThreadPool(int thread_number, int max_request):max_threads_number_(thread_number), max_requests_number_(max_request),stop_(false),works_() {
    if(thread_number <= 0 || max_request <= 0) {
        throw std::exception();
    }
    //threads_ init
    threads_ = std::vector<pthread_t>(max_threads_number_);

    for(int i = 0;i<max_threads_number_; ++i) 
    {
        //create pool
        if (pthread_create(&threads_[i], NULL, worker, this) != 0) {
            throw std::exception();
       
        }
        if (pthread_detach(threads_[i])) {
            throw std::exception();
        }
        printf("thread start!%d\n", threads_[i]);
    }
}

template<typename T>
ThreadPool<T>::~ThreadPool() {
    stop_ = true;
}

template<typename T>
bool ThreadPool<T>::append(T *request) {
    lock_.lock();
    if (this->works_.size() > max_requests_number_) {
        lock_.unlock();
        return false;
    }
    works_.push_back(request);
    printf("%d get work\n", getpid());
    sem_.post();
    lock_.unlock();
    return true;
}

template<typename T> 
void* ThreadPool<T>::worker(void* arg) {
    ThreadPool* self = (ThreadPool*)arg;
    self->run();
    return self;
}

template<typename T>
void ThreadPool<T>::run() {
    while(!stop_)
    {
        while(works_.empty())sem_.wait();
        lock_.lock();
        T* request = works_.front();
        works_.pop_front();
        lock_.unlock();
        ++i;
    }
}
void foo() {
    ++i;
}
typedef void (*task)();
int main() {
    ThreadPool<task> pool(200);
    task f = foo;
    for(int i = 0;i<10000;i++){printf("add work!\n");pool.append(&f);}
    sleep(1);
    printf("%d", i);
}

一般都是add work的时候会出现free两次

  • 写回答

1条回答 默认 最新

  • Kwo0D 2021-10-18 23:01
    关注

    已解决:
    因为可能会有多个线程同时被释放,然后同时进入下一步pop_front中,所以会导致double free,也解释了为什么这段代码如果工作成功,结果肯定是10000,因为此时没有同时被进入, 所以一定是10000

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 10月28日
  • 已采纳回答 10月20日
  • 创建了问题 10月18日

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器