c++中线程传递函数为什么是全局或者静态函数

首先,线程也是一种资源,受系统调度。在计算机中,运行程序都是通过地址来运行,所以,我们必须告知计算机该线程的起始地址,也就是传入函数的地址,所以函数应为全局函数或者静态函数。
在c++中,传入线程的函数可能是类中的函数,如果类中的函数不加static进行修饰,可以吗?
答案是不可以的。因为在类中,参数列表中都会有一个this指针,例如函数foo(int),在编译之后就会变成foo(int, class *this),所以直接将类中的函数传给线程是不可以的,因此一般会在函数前加static,这样子编译的时候就不会产生this指针参数。

我们看一个例子:

//线程池类,将它定义为模板类是为了代码复用。模板参数T是任务类
template<typename T>
class threadpool
{
public:  
    /*参数thread_number是线程池中线程的数量,max_requests是请求队列中最多允许的、等待处理请求的数量 */
    threadpool(int thread_number = 8, int max_requests = 10000);
    ~threadpool();
    //往请求队列中添加任务
    bool append(T* request);

    //工作线程运行函数
    static void* worker(void* arg);
    void run();

private:  
    int m_thread_number; //线程池中的线程数
    int m_max_requests; //请求队列中允许的最大请求数
    //pthread_t* m_threads; //描述线程池的数组,其大小为m_thread_number
    std::list<T*>m_workqueue; //请求队列
    std::vector<std::thread> p; //vector存储线程池
    std::mutex m;                          //锁   
    std::condition_variable cond;    //条件变量
    bool m_stop; //是否结束线程
};

template<typename T>
threadpool<T>::threadpool(int thread_number, int max_requests)
        : m_thread_number(thread_number), m_max_requests(max_requests), m_stop(false)
{
    if((thread_number <= 0) || (max_requests <= 0) )
        throw std::exception();
    
    //创建线程池
    p.reserve(thread_number); //先一次扩容
    for(int i = 0; i < thread_number; ++i)
    {
        p.push_back(std::thread(run));
        printf("create %d process \n", i);
        p[i].detach(); //线程分离
    }             
}

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

看到上面例子,我们定义了一个worker函数来作为创建线程的函数,在函数中我们立即调用了回调函数run。
如果我们将run函数直接作为启动线程的函数传入的话就会报错。


版权声明:本文为weixin_42250655原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。