回調函數程序員
回調函數通常是在封裝接口的時候,回調顯得特別重要,咱們首先假設有兩個程序員在寫代碼,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.回調能夠是同步也能夠是異步spa
2.同步能夠是單線程也能夠是多線程線程
異步必須是多線程或多進程(每一個進程能夠是單線程) ==> 換句話說,異步必須依靠多線程或多進程才能完成指針
同步回調:把函數b傳遞給函數a。執行a的時候,回調了b,a要一直等到b執行完才能繼續執行;blog
異步回調:把函數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\n"); callback(a); printf("A:end\n"); }
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\n"); printf("a = %d\n",a); sleep(5); printf("B:end\n"); } 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\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); }
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\n"); printf("a = %d\n",a); sleep(5); printf("B:end\n"); } 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。