協程的多執行緒切換

2021-06-28 00:40:15 字數 1663 閱讀 2614

我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。

另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住了,後續等待的協程得不到執行,整個程式此時也將死翹翹了。那麼,如果需要保證任意乙個協程都不阻塞,該怎麼做呢?

通常,協程主排程器管理著本執行緒中所有的協程,並依次排程這些協程執行,在乙個協程執行完之後,需要將執行許可權交給排程器,即進行 yield 操作,以便排程器能夠排程後續等待執行的協程。如果在某個協程內,含有阻塞操作,如開啟資料庫連線:

exe_non_block1();

open_db_conn(...);

exe_non_block2();

如上邊**所示,先執行了exe_non_block1, 然後開啟乙個資料庫連線,之後再執行exe_non_block2, 如果對這段**不做任何處理,倘若開啟資料庫連線需要耗時很多,那麼在這期間,整個程式就阻塞住了,這種情況是絕對不能容許的。怎麼解決呢?

我們看,先執行了exe_non_block2, 然後執行open_db_conn, 如果能夠把open_db_conn這個函式呼叫放到其他的執行緒中去執行,同時本協程yield,交出執行許可權;之後,當open_db_conn在其他執行緒執行完畢時,再切換到這個協程,並且能夠接著exe_non_block2繼續執行,那麼我們就可以解決上邊提出的問題, 保證整個主排程器不會阻塞,即便某乙個協程中需要進行阻塞操作,我們也可以把這段會阻塞的**放到其他執行緒中取執行,等執行完成後,再切換回來。換句話說,就是需要協程有這樣的特性:

能夠按照**順序依次在多個執行緒中執行

那麼,協程有這樣的特性嗎? 很幸運,協程是有的,因為在每次交出執行許可權(即yield)時,都會保留棧資訊。請看下邊的實驗**(multi_thread_switch.c):

#include "../libcoro/coro.h"

#include #include #include coro_context main_ctx;

coro_context parallel_ctx;

coro_context ctxa;

pthread_mutex_t mutex = pthread_mutex_initializer;

coro_context *current_main_ctx;

void parallel_coro_func(void *arg);

void* thread_main_func(void* arg)

void parallel_coro_func(void *arg)

}void coro_funca(void *arg)

}int main(void)

pthread_t mpid = pthread_self();

printf("main thread:%lu\n", mpid);

while(1)

return 0;

}

-eof-

協程的多執行緒切換

我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住...

多執行緒與協程爬蟲

網路爬蟲是一種高io密集型任務,所以傳統的程序或者多程序並不適合網路爬蟲。雖然由於cpython中全域性直譯器鎖gil的存在,無法真正意義上的實現多執行緒,但這種 不完美的多執行緒 依然可以大大提高爬蟲效率,當然在提高爬蟲效率方面還有大家所熟知的協程。比較官方的介紹我就不說了,畢竟瞅了一眼一大串,這...

多執行緒 多程序 協程

占用的資源 程序 執行緒 協程 程序的顆粒度太大,每次都要有上下的調入,儲存,調出。執行緒 乙個軟體的執行不可能是一條邏輯執行的,必定有多個分支和多個程式段,就好比要實現程式a,實際分成 a,b,c等多個塊組合而成 這裡的a,b,c就是執行緒,也就是說執行緒是共享了程序的上下文環境,的更為細小的cp...