linux下pthread_create创建的c语言风格的线程使用方式转换为c++类 c++11线程方式
admin
2024-03-25 16:03:03

在项目中碰到过用c语言方式实现的功能代码,包括创建线程用pthread_create这种方式,我本人用c++写代码,而且更喜欢c++代码风格,在改造的时候参考了如下2个链接,我自己先重复的记录下,方便日后参考:

在C++类中使用pthread实现多线程_jiajiahebangbang的博客-CSDN博客

C++11多线程std::thread入门使用以及对比分析pthread_欧特克_Glodon的博客-CSDN博客

现在pthread的api已经相当完善,使用其实现多线程难度不大,但是值得注意的一点是当想在类中使用pthread,调用pthread_create函数时,传入的运行函数,也就是下面这个原型的第三个参数void * ( * start_routine) (void *),如果是类的成员函数,必须是静态函数,否则将编译不通过,编译器会出一个这种错误。因为类的this指针在多线程下操作的问题,非静态的成员函数是不被允许传入的。

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                            void *(*start_routine) (void *), void *arg);

 

‘void*’ to ‘void* (*)(void*)’ c++

 

这里只能使用静态函数将带来一个问题,静态成员函数无法访问非静态的成员,这将带来许多不便,总不能将要用到的成员变量也改成静态的,这是不推荐的。我个人使用的是一种类似跳板的方式来解决。
首先这是一个pthread_create函数:

pthread_create(&thread, NULL, &test, (void *)this);

   

接下来是test函数的实现,function即为自己真正要执行的函数,这样就解决了需要访问非静态成员的问题。当然如果要传的参数比较多,自己写一个struct传递就行了。

static void *test(void * arg) {
    return static_cast(arg)->function();
}

另外,也可以用标准库的thread,效率上个人认为是差不多的,不过thread是可以跨平台的。

std::thread thread(&test, this);

#include
#include
#include
#include

// 注意pthread_*函数返回的异常值,为了简单(偷懒),我没有去处理它们

pthread_mutex_t mutex;
pthread_cond_t condvar;

std::queue msgQueue;
struct Produce_range {
    int start;
    int end;
};

void *producer(void *args)
{
    int start = static_cast(args)->start;
    int end = static_cast(args)->end;
    for (int x = start; x < end; x++) {
        usleep(200 * 1000);
        pthread_mutex_lock(&mutex);
        msgQueue.push(x);
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&condvar);
        printf("Produce message %d\n", x);
    }
    pthread_exit((void *)0);
    return NULL;
}

void *consumer(void *args)
{
    int demand = *static_cast(args);
    while (true) {
        pthread_mutex_lock(&mutex);
        if (msgQueue.size() <= 0) {
            pthread_cond_wait(&condvar, &mutex);
        }
        if (msgQueue.size() > 0) {
            printf("Consume message %d\n", msgQueue.front());
            msgQueue.pop();
            --demand;
        }
        pthread_mutex_unlock(&mutex);
        if (!demand) break;
    }
    pthread_exit((void *)0);
    return NULL;
}


int main()
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&condvar, NULL);

    pthread_t producer1, producer2, producer3, consumer1, consumer2;

    Produce_range range1 = {0, 10};
    pthread_create(&producer1, &attr, producer, static_cast(&range1));
    Produce_range range2 = {range1.end, range1.end + 10};
    pthread_create(&producer2, &attr, producer, static_cast(&range2));
    Produce_range range3 = {range2.end, range2.end + 10};
    pthread_create(&producer3, &attr, producer, static_cast(&range3));

    int consume_demand1 = 20;
    int consume_demand2 = 10;
    pthread_create(&consumer1, &attr, consumer,
            static_cast(&consume_demand1));
    pthread_create(&consumer2, &attr, consumer,
            static_cast(&consume_demand2));

    pthread_join(producer1, NULL);
    pthread_join(producer2, NULL);
    pthread_join(producer3, NULL);
    pthread_join(consumer1, NULL);
    pthread_join(consumer2, NULL);
}

#include
#include
#include
#include
#include

// 注意某些调用可能会抛出std::system_error,没有去捕获
std::mutex mutex;
std::condition_variable condvar;

std::queue msgQueue;

void producer(int start, int end)
{
    for (int x = start; x < end; x++) {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        {        
            std::lock_guard guard(mutex);
            msgQueue.push(x);
        }
        printf("Produce message %d\n", x);
        condvar.notify_all();
    }
}

void consumer(int demand)
{
    while (true) {
        std::unique_lock ulock(mutex);
        condvar.wait(ulock, []{ return msgQueue.size() > 0;});
        // wait的第二个参数使得显式的double check不再必要
        printf("Consume message %d\n", msgQueue.front());
        msgQueue.pop();
        --demand;
        if (!demand) break;
    }
}


int main()
{
    std::thread producer1(producer, 0, 10);
    std::thread producer2(producer, 10, 20);
    std::thread producer3(producer, 20, 30);
    std::thread consumer1(consumer, 20);
    std::thread consumer2(consumer, 10);

    producer1.join();
    producer2.join();
    producer3.join();
    consumer1.join();
    consumer2.join();
}

相关内容

热门资讯

春风送暖赴梅约 莒县龙山解锁春... 齐鲁网·闪电新闻3月31日讯 春和景明,惠风送暖。当下,莒县龙山镇东楼村梅园的梅花如期绽放,漫山遍野...
视频丨开启一场“说走就走”之旅... 来源:央视新闻客户端今年以来,外国人入境人次的持续增长迅速带热了深圳的“文旅流量”“商贸流量”。经深...
靠中药养生这件事终于没那么苦了 现在,年轻人去医院的理由,除了挂号、看病、做检查,可能还得再加一项:买面包。 在天津中医药大学第一附...
荠菜虾丸汤:春日鲜味,给孩子的... 春季万物复苏,也是孩子猛涨个的黄金期,作为家长不得不重视起来,所以调整好饮食很重要,今天分享一道特别...