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

在项目中碰到过用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();
}

相关内容

热门资讯

写人作文的方法和技巧 写人作文的方法和技巧写人作文的方法和技巧如下:1、肖像描写(外貌描写)通过对容貌、神情、姿态、服饰、...
保安人员培训记录有什么内容? 保安人员培训记录有什么内容?您好,玖玖泰丰验厂网可免费为您提供验厂咨询,十年验厂老品牌,百分百通过验...
有什么好看级数多的动漫 有什么好看级数多的动漫驱魔少年106家庭教师203挺好妖精的尾巴。灼眼的夏娜三季共75集 旋风管家(...
男人如果能够给你什么样的感受就... 男人如果能够给你什么样的感受就说明他是真心爱你的?一个男人如果能够给你非常幸福,而且非常快乐的感受,...
这个动漫人物是谁了。叫什么? 这个动漫人物是谁了。叫什么?舒克和贝塔里的贝塔贝塔~~~~~舒克和贝塔里的贝塔最早的动画,舒克与贝塔...
他还能回到我身边吗?好痛…… 他还能回到我身边吗?好痛……男人的心一旦不在你身上了,那么你哭是错,闹是错,连呼吸活着都是一种错,这...
pda、草木良品、抚柔的薰衣草... pda、草木良品、抚柔的薰衣草纯露哪种比较好前两个找不到。。。最后个品质不确定,但看了各种介绍写上保...
佳人伊憔悴~来个接下一句的 佳人伊憔悴~来个接下一句的雄霸其兴隆。
我的模拟人生:漂流物语安装完以... 我的模拟人生:漂流物语安装完以后运行的时候说找不到与DirectX9.0c兼容的图形适配器怎么办啊~...
求一首非常另类的中文歌曲,在K... 求一首非常另类的中文歌曲,在KTV一唱就能带动全场气氛的,最好是搞笑的!来来~ 小猪我向阁下推荐几首...
家风是什么班会 家风是什么班会传统习俗 家规 家训 礼仪 等等 具有很强的约束力
家乡的变化手抄报。 家乡的变化手抄报。 资料:在一个美丽的星期六,我会到我非常想念的老家。我的老家是一个,春天阳光明...
好看穿越电视剧 好看穿越电视剧除了神话 寻秦记 穿越时空的爱恋 最好是现穿古你可以期待一下有部新剧《宫...
求网游小说推荐。谢谢! 求网游小说推荐。谢谢!失落叶――――《 网游之纵横天下》 游戏生涯 作者将诸多元素完美的融合到一部大...
百变机兽之洛洛历险记 百变机兽之洛洛历险记洛洛的死敌,也就是猛兽族的机战王,他(她)叫什么?最早出现在第几集?晶晶,40集...
“势不可挡”是什么意思? “势不可挡”是什么意思?一个人是谁吗……不够的问题……不可抵挡的意思势不可挡的意思是来势迅猛,不可抵...
一个女人发表说说写的我要正正经... 一个女人发表说说写的我要正正经经追一个女生是啥意思一种游戏,赞或者评论了那条说说的人就要发一条一样的...
有几次睡得迷迷糊糊听到妈妈叫我... 有几次睡得迷迷糊糊听到妈妈叫我这是什么意思想家了/常回家看看啊呵呵 梦境是你的潜意识的体现,虽然在真...
你是怎么理解“相濡以沫,不如相... 你是怎么理解“相濡以沫,不如相忘于江湖”这句话的?意思就是说两个人在一起有时候倒不如分开的好,差不多...
后妈有好的吗 后妈有好的吗有人说后妈都很坏,不是自己的孩子,对他不好也是理所当然。当然不能以偏概全,有的后妈还是很...