回调函数中同步回调和异步回调的区别
回调函数
回调函数一般是在封装接口的时候,回调显得特别重要,我们首先假设有两个程序员在写代码,A程序员写底层驱动接口,B程序员写上层应用程序,然而此时底层驱动接口A有一个数据d需要传输给B,此时有两种方式:
- A将数据d存储好放在接口函数中,B自己想什么时候去读就什么时候去读,这就是我们经常使用的函数调用,此时主动权是B
- A实现回调机制,当数据变化的时候才将通知B,你可以来读取数据了,然后B在用户层的回调函数中读取速度d,完成OK。此时主动是A
第一种方法B是无法知道数据d何时会发生变化,只有B自己定时去读取或者在需要的时候去取数据。
第二种方法是A在数据发生变化后主动将数据告诉B,效率比第一种高。
回调函数的实现
其实回调函数就是一个通过函数指针调用的函数。如果用户层B把函数的指针(地址)作为参数传递给底层驱动A,当这个指针在A中被用为调用它所指向的函数时,我们就说这是回调函数。
注意: 是在A中被调用,这里看到尽管函数是在B中,但是B却不是自己调用这个函数,而是将这个函数的函数指针通过A的接口函数传自A中了,由A来操控执行,这就是回调的意义所在
同步回调和异步回调的概念
- 回调可以是同步的也可以是异步的
- 同步可以是单线程也可以是多线程,异步必须是多线线程或多进程。
同步回调: 把函数b传递给函数a。执行a的时候,回调了b,a要一直等到b执行完才能继续执行。会阻塞当前函数b
异步回调:把函数b传递给函数a。执行a的时候,回调了b,然后a就继续往后执行,b独自执行。不会阻塞当前函数b
看例子
A.h
#ifndef A_H
#define A_H
typedef void (*pcb)(int a); //函数指针定义,后面可以直接使用pcb,方便
void SetCallBackFun(int a, pcb callback);
同步回调
ExpA.c
#include <stdio.h>
#include "A.h"
//-----------------------底层实现A-----------------------------
//留给应用层B的接口函数
void SetCallBackFun(int a, pcb callback)
{
printf("A:start\n");
callback(a);
printf("A:end\n");
}
ExpB.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "A.h"
//-----------------------应用者B-------------------------------
void fCallBack(int a) // 应用者增加的函数,此函数会在A中被执行
{
//do something
printf("B:start\n");
printf("a = %d\n",a);
sleep(5);
printf("B:end\n");
}
int main(void)
{
SetCallBackFun(4,fCallBack);
return 0;
}
异步回调
ExpA.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\n");
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\n");
//阻塞,等待线程pid结束,才往下走
pthread_join(pid,NULL);
}
ExpB.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "A.h"
//-----------------------应用者B-------------------------------
void fCallBack(int a) // 应用者增加的函数,此函数会在A中被执行
{
//do something
printf("B:start\n");
printf("a = %d\n",a);
sleep(5);
printf("B:end\n");
}
int main(void)
{
SetCallBackFun(4,fCallBack);
return 0;
}
运行结果比较
同步回调 | 异步回调 |
---|---|
A:start | A:start |
B:start | A:end |
a = 4 | B:start |
B:end | a = 4 |
A:end | B:end |
由执行结果可以看出:同步回调,A需要等待B执行完成才能执行A剩余的操作;异步回调,A刚执行B,不必等待B结束,就执行A剩余的操作,之后B的操作也随之end。 |
转载
https://www.cnblogs.com/still-smile/p/12048078.html