并發(fā)編程筆記1

上下文切換

單核處理器是如何支持多線程編程的? CPU通過給每個線程分配CPU時間片來實現(xiàn)。

  • 時間片是CPU分配給各個線程的時間,時間片非常短,CPU通過不停切換線程執(zhí)行,切換時間很快,讓人感覺是在同時執(zhí)行。
  • CPU通過時間片算法來循環(huán)執(zhí)行任務,當前任務執(zhí)行完一個時間片后會切換到下一個任務,切換前輝保存上一個任務的狀態(tài),便于下次切回的時候可以再加載這個任務的狀態(tài)。任務從保存到再加載的過程就是一次上下文切換。
  • 因為線程有創(chuàng)建和上下文的切換的開銷,并發(fā)執(zhí)行累加操作次數(shù)沒有很高的時候,速度會比串行執(zhí)行慢。

測試上下文切換次數(shù)和時長的工具

  • 使用Lmbench3可以測量上下文切換的時長
  • 使用vmstat可以測量上下文切換的次數(shù)

如何減少上下文切換

  • 無鎖并發(fā)編程。多線程競爭鎖時,會引起上下文切換,可以用些方法來避免用鎖。比如對數(shù)據(jù)id計算取模分段,不同線程處理不同段的數(shù)據(jù)。
  • CAS算法。CAS:Compare and Swap, 翻譯成比較并交換。 java.util.concurrent包中借助CAS實現(xiàn)了區(qū)別于synchronouse同步鎖的一種樂觀鎖。
  • 使用最少線程。避免創(chuàng)建不需要的線程。比如任務很少,不比創(chuàng)建大量線程,可能會導致大量線程處于等待狀態(tài)。
  • 協(xié)程:在單線程里實現(xiàn)多任務的調(diào)度,并在單線程里維持多個任務間的切換。具體java如何實現(xiàn)協(xié)程要找個時間研究下。

死鎖

dump分析死鎖

  • 一旦出現(xiàn)死鎖,業(yè)務是可感知的,不能繼續(xù)提供服務。只能通過dump線程查看是哪個線程出現(xiàn)了問題。
  • Jstack是JDK自帶的命令行工具,主要用于線程Dump分析
  1. 我們先用Jps來查看java進程id(或者Linux的ps命令)


    image.png
  2. jstack的使用


    image
  3. jstack輸出線程dump信息到文件


    image
  4. 查看文件,關鍵字是at DeadThread.run,比如at DeadThread.run(DeadThread.java:37),說明Thread-1實在DeadThread類的37行處發(fā)生死鎖


    image.png

避免死鎖的常見方法

  • 避免一個線程同時獲取多個鎖。
  • 避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源。
  • 嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內(nèi)部鎖機制。
  • 對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失效的情況。
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容