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();
}

相关内容

热门资讯

国庆黄金周景区情况:大同古城半... 文| 芙昕 编辑 | 芙昕 国庆长假,很多人都计划着出门走走,可一到了那些热门景点,看到的往往不是山...
来大东北一共分两步:先“冷藏”... 还在被“东北=冰窖”的刻板印象吓退? 南方的“小土豆”们 别急着裹紧小棉袄 这个冬天 让“气候缓冲带...
第三届“长城之约”活动在河北涞... 11月15日,第三届"长城之约"全球推广活动暨世界文化遗产对话15日在河北省保定市涞源县启幕。 本次...
巴厘岛:时光在此停驻 (自由行... 曾几何时,世人只知巴厘岛而不知印尼。巴厘岛的美太过耀眼,以至于人们常常忘记——它只是印尼万千岛屿中最...