多線程進(jìn)程fork出來的進(jìn)程是單線程還是多線程?
本文轉(zhuǎn)載自微信公眾號【編程珠璣】(shouwangxiansheng)。
一個多線程進(jìn)程fork出來的進(jìn)程是多線程還是單線程的?先說結(jié)論:是單線程的。
實踐
口說無憑,我們先寫段代碼實踐驗證一下。
- // multiThread.cc
- #include <unistd.h>
- #include <atomic>
- #include <chrono>
- #include <iostream>
- #include <thread>
- std::atomic<bool> start{false};
- void threadfunc() {
- while (!start) {
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
- while (start) {
- std::this_thread::sleep_for(std::chrono::seconds(1));
- std::cout << "thread func,pid:" << getpid() << std::endl;
- }
- }
- int main() {
- std::thread t1(threadfunc);
- // daemon(0, 1); // 后臺執(zhí)行
- start.store(true);
- t1.join(); // 等待threadfunc運(yùn)行結(jié)束
- return 0;
- }
編譯運(yùn)行:
- $ g++ -o multiThread multiThread.cc -lphtread
- $ ./multiThread
- thread func,pid:9901
- thread func,pid:9901
- thread func,pid:9901
結(jié)果正常,線程不斷循環(huán)打印信息。那如果啟動線程后,再fork呢?即將代碼中daemon的相關(guān)行的注釋去掉,再編譯運(yùn)行。
運(yùn)行這個例子,我們會發(fā)現(xiàn),程序立馬退出了,沒有打印我們預(yù)想的內(nèi)容。
為什么
為什么會這樣呢?實際上,fork的時候會拷貝父進(jìn)程的數(shù)據(jù)內(nèi)容,即寫時復(fù)制,但是,像啟動運(yùn)行的線程,是不會被“復(fù)制”過去的。也就是說,從父進(jìn)程fork出來的子進(jìn)程,將會是單線程的。這也就給了我們一些啟示:
如果在API中需要啟動工作線程,則工作線程需要在daemon化之后再啟動。
怎么理解呢?比如說,你設(shè)計了某一個功能,你的功能是需要啟動一個線程來進(jìn)程工作,那么你在使用的時候,就必須要特別注意這種fork進(jìn)程的場景,即需要在fork之后啟動線程,才能保證線程能夠正常啟動并工作。