由git checkout引發(fā)的python多線程思考

聲明:并非標題黨浮定,確實是一件實際的案例,這里只是詳細捋一下自己的分析過程

  • 背景
    某日层亿,進行git checkout xxx_branch時桦卒,總是報出Unlink of file 'logs/Crawler_2019-11-02.log' failed. Should I try again? (y/n) 的錯誤,這是一份多線程爬蟲的日志報告匿又,查看stackoverflow方灾,發(fā)現原因是:有程序在使用這個文件導致不能正確地進行遷移,常規(guī)解決辦法:查看任務管理器碌更,找到占用這個文件的進程裕偿,把它kill,但這又治標不治本痛单,想到了每次出現這個的原因是:爬蟲任務每次都不能正常結束嘿棘,強制結束導致的資源沒有被正確釋放,且該任務為多線程任務桦他,導致出現很多僵尸線程蔫巩。

  • 問題:
    對占用.log文件的程序正確退出并釋放資源,該程序分為兩個階段:

    • 多線程收集各個具體頁面的URL
    • 多線程收集各個具體頁面的contents

    表現出來的行為是每次程序都在第二個階段卡住快压,強制結束

  • 解決思路:

    • 首先懷疑是queue.Queue()的問題圆仔,不放心它的task_done()join()的配合,打印出的信息發(fā)現確實是task_done()使qsize()的數目-1蔫劣,第一階段執(zhí)行結束坪郭,qsize()到0,queue這邊沒問題

    • 其次懷疑是多線程這邊實現的問題脉幢,使用的concurrrent.futures歪沃,相比于threading這種自己動手豐衣足食的做法,有點不放心嫌松,查看stackoverflow1 stackoverflow2沪曙,這個東西確實也是使用了threading

      甚至懷疑過使用這種多線程的做法是不是把默認的主線程阻塞了萎羔,但試了一下這種想法也太傻了

def worker():
    while True:
        item = q.get()
        if item is None:
            break
        do_work(item)
        q.task_done()

q = queue.Queue()
threads = []
for i in range(num_worker_threads):
    t = threading.Thread(target=worker)
    t.start()
    threads.append(t)

for item in source():
    q.put(item)

# block until all tasks are done
q.join()

# stop workers
for i in range(num_worker_threads):
    q.put(None)
for t in threads:
    t.join()

看到以上代碼段的時候來源液走,特別是#stop workers這一段,確信:join()的作用只是起到barrier的作用,用于同步缘眶,并不能結束子線程的執(zhí)行嘱根,在考慮這種多線程問題的時候,還要設置子線程退出機制巷懈,對于子線程的退出機制:

  • 對于threading该抒,可以設置daemon=True,將子線程設置為守護線程顶燕,主線程退出時凑保,子線程自動退出;
  • 對于concurrent.futures, 在stackoverflow1中涌攻,講到關于守護進程的設置愉适,并不能真正的daemon

對于子線程退出的問題,我采用的做法癣漆,是通過判斷queue為空,子線程退出剂买,這適用于“快生產惠爽、慢消費”場景(不同生產消費場景思考)

  if self.news_detail_url_queue.empty():
     break
  • 關鍵
    這些并不能解決阻塞問題,后來檢查一部分多線程并發(fā)實現的代碼時發(fā)現:
    def parallel_do(func, args_list, max_workers=None, mode='thread'):
      max_workers = thread_max_workers if not max_workers else max_workers
      exe = cf.ThreadPoolExecutor(max_workers=max_workers) if mode == 'thread' else cf.ProcessPoolExecutor(max_workers=max_workers)
      with exe as executor:
          if args_list is None:
              for t in range(max_workers):
                  executor.submit(func)
          else:
              executor.map(func, args_list)
    

使用with statement雖然保證了子線程的退出和資源的正確釋放瞬哼,這也是導致整個執(zhí)行過程被阻塞的根源婚肆。 也就是不能使parallel_do之間實現并發(fā),要想并發(fā)坐慰,可以考慮去除with statement较性。

  • 總結

    • 使用多線程時要注意子線程的退出條件,否則出現 zombie thread结胀;
    • concurrent.futures內部使用的仍然是threading實現的多線程赞咙;
    • 使用queue.join()要注意對task_done()的正確調用,否則會阻塞糟港;

更多關于git的內容可參考本人博客:老香椿(https://laoxiangchun.cn/2020/05/30/Git/how-to-use-git/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末攀操,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子秸抚,更是在濱河造成了極大的恐慌速和,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剥汤,死亡現場離奇詭異颠放,居然都是意外死亡,警方通過查閱死者的電腦和手機吭敢,發(fā)現死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門碰凶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事痒留∏绰螅” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵伸头,是天一觀的道長匾效。 經常有香客問我,道長恤磷,這世上最難降的妖魔是什么面哼? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮扫步,結果婚禮上魔策,老公的妹妹穿的比我還像新娘。我一直安慰自己河胎,他們只是感情好闯袒,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著游岳,像睡著了一般政敢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胚迫,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天喷户,我揣著相機與錄音,去河邊找鬼访锻。 笑死褪尝,一個胖子當著我的面吹牛,可吹牛的內容都是我干的期犬。 我是一名探鬼主播河哑,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼龟虎!你這毒婦竟也來了灾馒?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤遣总,失蹤者是張志新(化名)和其女友劉穎睬罗,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體旭斥,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡容达,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了垂券。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片花盐。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡羡滑,死狀恐怖,靈堂內的尸體忽然破棺而出算芯,到底是詐尸還是另有隱情柒昏,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布熙揍,位于F島的核電站职祷,受9級特大地震影響,放射性物質發(fā)生泄漏届囚。R本人自食惡果不足惜有梆,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望意系。 院中可真熱鬧泥耀,春花似錦、人聲如沸蛔添。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迎瞧。三九已至陨囊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夹攒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工胁塞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咏尝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓啸罢,卻偏偏與公主長得像编检,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扰才,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容

  • 線程 操作系統(tǒng)線程理論 線程概念的引入背景 進程 之前我們已經了解了操作系統(tǒng)中進程的概念衩匣,程序并不能單獨運行蕾总,只有...
    go以恒閱讀 1,645評論 0 6
  • 串行:同一個時間段只干一件事 并行:同一個時間段可以干多件事 并發(fā) V.S. 并行并發(fā)是指一個時間段內柄延,有幾個程序...
    蘇慕漓閱讀 4,885評論 0 5
  • 必備的理論基礎 1.操作系統(tǒng)作用: 隱藏丑陋復雜的硬件接口蚀浆,提供良好的抽象接口。 管理調度進程,并將多個進程對硬件...
    drfung閱讀 3,541評論 0 5
  • 引言 抨擊線程的往往是系統(tǒng)程序員市俊,他們考慮的使用場景對一般的應用程序員來說杨凑,也許一生都不會遇到……應用程序員遇到的...
    尋找無雙丶閱讀 1,417評論 0 2
  • 一文讀懂Python多線程 1、線程和進程 計算機的核心是CPU摆昧,它承擔了所有的計算任務撩满。它就像一座工廠,時刻在運...
    星丶雲閱讀 1,455評論 0 4