linux 下实现简单的异步多线程任务分发

linux 下实现简单的异步多线程任务分发

异步多任务并行处理在linux场景下有很多种实现方式。
当前主流有几种方案:多进程方案,1 master+N workers 方式,类似apache等等;多线程方案,或维护一个线程池。
本例子实现一个简单的单进程多线程异步分发任务模型。本实现有如下特点:
* 维护线程简单
* 直接可以传送函数,函数的参数
* 线程之间使用消息队列通信,实时性高,简单
* 可以实现简单的与主线程分离的任务
* swoole中,nodejs中的异步任务,需要在特定的io或事件场合,才可以异步,并不是随时可以异步,本例子实现随时任何情形都可以异步
受限于消息队列等因素,本例子还有未实现功能:
* 线程间没有锁机制,共享数据将不安全
* linux消息队列每个元素最大只能65535字节
* 暂时不能实现协程调度,工作线程和主线程是异步的,但是1个工作线程同时只能接受到1个任务,必须执行完才能接下一个任务。如果总共三个工作线程,每一个都阻塞,那就不能继续执行新的任务。
后续更新:
* 使用getcontext,setcontext,swapcontext来实现协程调度
* 实现有锁调用和无锁调用两种方式

code.c:

/*
 * 实现简单消息队列分发任务异步执行
 * c99 thread.c -o thread -l pthread -D _XOPEN_SOURCE
 * */
#define _XOPEN_SOURCE 1
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdarg.h>
#include <string.h>

#define LOGF(STR, ...) logfmt(STR, __FILE__,__LINE__,__func__,##__VA_ARGS__)

int msgqid = 0;             // 用于主线程和worker线程通信的消息队列id,由主线程申请
int msgtype = 9812;         // 消息标识符,类型
int IPC_KEY = 100011;       // 申请消息的IPC_KEY 本应该用ftok获得

/* 消息队列消息结构 */
/* 以下消息队列中保存的指针,只在当前运行进程内有效,其他进程或者重启进程将失效 */
typedef struct message {
    long msg_type;              /* 消息标识符 */
    void* (*func)(void*);       /* 调用函数指针 在不同进程和进程重启后将失效 切记 */
    void* param;                /* 此函数的参数 */
    void** retval;              /* 此函数的返回值接收地址 发送方提供 发送方先申请好空间 */
    void* (*callback)(void* retval, void*origin_param);   /* 完成后的callback函数 参数依次是 返回值,上次调用的函数的参数 */
} message;

/* 线程任务单元 */
typedef struct threadtask {
    pthread_t tid;
    int is_working;
    int working_times;
} threadtask;
/* 小线程池 */
typedef struct taskpool {
     threadtask* pool;
     int len;
} taskpool;

taskpool* mainpool;

void logfmt(const char* str, const char* file, const int line, const char* func, ...);

/*protected 线程的main函数 task consumer */
void* taskconsumer(void*ptr) {
    threadtask* myth = (threadtask*)ptr;
    struct message msgq;
    int i = 0;
    for (i=0; ;i++) {
        msgrcv(msgqid, &msgq, sizeof(message)-sizeof(long), msgtype, 0);
        myth->is_working = 1;
        myth->working_times++;
        LOGF("threadtask(%ld) got a task: loopid=%d taskfunc=%p param=%d\n", myth->tid, i, msgq.func, (msgq.param==NULL?0:*(int*)msgq.param));

        if (msgq.func == NULL) {
            LOGF(&#
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值