zoukankan      html  css  js  c++  java
  • 同步回调函数和异步回调函数

    回调函数

    回调函数一般是在封装接口的时候,回调显得特别重要,我们首先假设有两个程序员在写代码,A程序员写底层驱动接口,B程序员写上层应用程序,然而此时底层驱动接口A有一个数据d需要传输给B,此时有两种方式: 
    1.A将数据d存储好放在接口函数中,B自己想什么时候去读就什么时候去读,这就是我们经常使用的函数调用,此时主动权是B。 
    2.A实现回调机制,当数据变化的时候才将通知B,你可以来读取数据了,然后B在用户层的回调函数中读取速度d,完成OK。此时主动权是A。 
    很明显第一种方法太低效了,B根本就不知道什么时候该去调用接口函数读取数据d。而第二种方式由于B的读取数据操作是依赖A的,只有A叫B读数据,那么B才能读数据。也即是实现了中断读取。 
    那么回调是怎么实现的呢,其实回调函数就是一个通过函数指针调用的函数。如果用户层B把函数的指针(地址)作为参数传递给底层驱动A,当这个指针在A中被用为调用它所指向的函数时,我们就说这是回调函数。 
    注意:是在A中被调用,这里看到尽管函数是在B中,但是B却不是自己调用这个函数,而是将这个函数的函数指针通过A的接口函数传自A中了,由A来操控执行,这就是回调的意义所在。 

    同步回调和异步回调

    首先,理解几个概念:

    1.回调可以是同步也可以是异步

    2.同步可以是单线程也可以是多线程

       异步必须是多线程或多进程(每个进程可以是单线程) ==> 换句话说,异步必须依靠多线程或多进程才能完成

    同步回调:把函数b传递给函数a。执行a的时候,回调了b,a要一直等到b执行完才能继续执行;

    异步回调:把函数b传递给函数a。执行a的时候,回调了b,然后a就继续往后执行,b独自执行。

    直接看例子

    A.h

    #ifndef A_H
    #define A_H
    
    typedef void (*pcb)(int a); //函数指针定义,后面可以直接使用pcb,方便
    void SetCallBackFun(int a, pcb callback);
    
    #endif

    同步回调

    synA.c

    #include <stdio.h>
    #include "A.h"
     
    //-----------------------底层实现A-----------------------------
    //留给应用层B的接口函数
    void SetCallBackFun(int a, pcb callback)
    {
      printf("A:start
    ");
      callback(a);
      printf("A:end
    ");
    }

    synB.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include "A.h"
    //-----------------------应用者B-------------------------------
     
    void fCallBack(int a) // 应用者增加的函数,此函数会在A中被执行
    {
      //do something
      printf("B:start
    ");
      printf("a = %d
    ",a);
      sleep(5);
      printf("B:end
    ");
    }
     
    int main(void)
    {
      SetCallBackFun(4,fCallBack);
      return 0;
    }

    异步回调

    asynA.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include "A.h"
    //-----------------------底层实现A-----------------------------
    typedef struct parameter{
      int a ;
      pcb callback;
    }parameter;
     
    void* callback_thread(void *p1)//此处用的是一个线程
    {
      //do something
      parameter* p = (parameter*)p1 ;
      sleep(5);
      p->callback(p->a);//函数指针执行函数,这个函数来自于应用层B
    }
     
    //留给应用层B的接口函数
    void SetCallBackFun(int a, pcb callback)
    {
      printf("A:start
    ");
      parameter *p = malloc(sizeof(parameter)) ;
      p->a = a;
      p->callback = callback;
     
      //创建线程
      pthread_t pid;
      pthread_create(&pid,NULL,callback_thread,(void *) p);
      printf("A:end
    ");
     
      //阻塞,等待线程pid结束,才往下走
      pthread_join(pid,NULL);
    }

    asynB.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include "A.h"
    //-----------------------应用者B-------------------------------
    void fCallBack(int a) // 应用者增加的函数,此函数会在A中被执行
    {
      //do something
      printf("B:start
    ");
      printf("a = %d
    ",a);
      sleep(5);
      printf("B:end
    ");
    }
     
    int main(void)
    {
      SetCallBackFun(4,fCallBack);
      return 0;
    }

    运行结果比较:

    同步回调 异步回调
    A:start
    B:start
    a = 4
    B:end
    A:end
    A:start
    A:end
    B:start
    a = 4
    B:end

    由执行结果可以看出:同步回调,A需要等待B执行完成才能执行A剩余的操作;异步回调,A刚执行B,不必等待B结束,就执行A剩余的操作,之后B的操作也随之end。

  • 相关阅读:
    正则表达式中的贪婪模式与非贪婪模式详解
    关于Python中正则表达式的反斜杠问题
    每日思考记录(1)
    软件设计——2018年上半年选择题重要知识点
    统一过程UP
    软件设计复习7
    软件设计复习6
    软件设计复习5
    软件设计复习4
    软件设计复习3
  • 原文地址:https://www.cnblogs.com/still-smile/p/12048078.html
Copyright © 2011-2022 走看看