Shell逐行處理文本求和,我人傻了...
本文轉(zhuǎn)載自微信公眾號(hào)「編程珠璣」,作者守望先生。轉(zhuǎn)載本文請(qǐng)聯(lián)系編程珠璣公眾號(hào)。
一個(gè)多線程進(jìn)程fork出來的進(jìn)程是多線程還是單線程的?先說結(jié)論:是單線程的。
實(shí)踐
口說無憑,我們先寫段代碼實(shí)踐驗(yàn)證一下。
- // 來源:公眾號(hào)【編程珠璣】
- // 作者:守望先生
- // 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); // 后臺(tái)執(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)打印信息。那如果啟動(dòng)線程后,再fork呢?即將代碼中daemon的相關(guān)行的注釋去掉,再編譯運(yùn)行。
在《如何讓程序真正地后臺(tái)運(yùn)行?》中我們知道,daemon實(shí)際上做了進(jìn)程的fork。
運(yùn)行這個(gè)例子,我們會(huì)發(fā)現(xiàn),程序立馬退出了,沒有打印我們預(yù)想的內(nèi)容。
為什么
為什么會(huì)這樣呢?實(shí)際上,我們?cè)凇度绾问褂胒ork創(chuàng)建進(jìn)程》中就提到過,fork的時(shí)候會(huì)拷貝父進(jìn)程的數(shù)據(jù)內(nèi)容,即寫時(shí)復(fù)制,但是,像啟動(dòng)運(yùn)行的線程,是不會(huì)被“復(fù)制”過去的。也就是說,從父進(jìn)程fork出來的子進(jìn)程,將會(huì)是單線程的。這也就給了我們一些啟示
如果在API中需要啟動(dòng)工作線程,則工作線程需要在daemon化之后再啟動(dòng)
怎么理解呢?比如說,你設(shè)計(jì)了某一個(gè)功能,你的功能是需要啟動(dòng)一個(gè)線程來進(jìn)程工作,那么你在使用的時(shí)候,就必須要特別注意這種fork進(jìn)程的場(chǎng)景,即需要在fork之后啟動(dòng)線程,才能保證線程能夠正常啟動(dòng)并工作。