多線程進程fork出來的進程是單線程還是多線程?
本文轉載自微信公眾號【編程珠璣】(shouwangxiansheng)。
一個多線程進程fork出來的進程是多線程還是單線程的?先說結論:是單線程的。
實踐
口說無憑,我們先寫段代碼實踐驗證一下。
- // 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); // 后臺執行
- start.store(true);
- t1.join(); // 等待threadfunc運行結束
- return 0;
- }
編譯運行:
- $ g++ -o multiThread multiThread.cc -lphtread
- $ ./multiThread
- thread func,pid:9901
- thread func,pid:9901
- thread func,pid:9901
結果正常,線程不斷循環打印信息。那如果啟動線程后,再fork呢?即將代碼中daemon的相關行的注釋去掉,再編譯運行。
運行這個例子,我們會發現,程序立馬退出了,沒有打印我們預想的內容。
為什么
為什么會這樣呢?實際上,fork的時候會拷貝父進程的數據內容,即寫時復制,但是,像啟動運行的線程,是不會被“復制”過去的。也就是說,從父進程fork出來的子進程,將會是單線程的。這也就給了我們一些啟示:
如果在API中需要啟動工作線程,則工作線程需要在daemon化之后再啟動。
怎么理解呢?比如說,你設計了某一個功能,你的功能是需要啟動一個線程來進程工作,那么你在使用的時候,就必須要特別注意這種fork進程的場景,即需要在fork之后啟動線程,才能保證線程能夠正常啟動并工作。