android 多線程 —上下文切換

java 中的多線程在代碼層面是通過 new 多個(gè) Thread 或是線程池實(shí)現(xiàn)的,這只是表象,我們需要繼續(xù)審圖探究。最終的計(jì)算任務(wù)是由 CPU 完成的,那么我們只要知道 CPU 如何調(diào)度 Thread 的就行了,這就引出了 CPU 時(shí)間這個(gè)概念

無論是單核還是多核 CPU 都是支持多線程的,CPU 通過給每個(gè)線程分配 CPU 時(shí)間片來實(shí)這個(gè)機(jī)制,這個(gè)時(shí)間片非常短,所以 CPU 通過不停地切換線程執(zhí)行,讓我們感覺多個(gè)線程是同時(shí)執(zhí)行的,時(shí)間片一般是幾十毫秒(ms)

然后我們?cè)傧胍幌耄覀冇?jì)算的數(shù)據(jù)存在內(nèi)存,但是 CPU 不在內(nèi)存中計(jì)算數(shù)據(jù),而是在 CPU 所屬的寄存器中計(jì)算任務(wù),這就涉及到 內(nèi)存和 CPU 寄存器相互交互數(shù)據(jù)了。一個(gè)時(shí)間片段很短,很大可能一個(gè)線程的任務(wù)完不成,但是在這個(gè) CPU 時(shí)間段結(jié)束后由別的線程搶到了隱形機(jī)會(huì),那么 CPU 就得執(zhí)行別的線程的任務(wù),此時(shí)上一個(gè)線程未完成的任務(wù)的數(shù)據(jù)需要保存起來,然后加載下一個(gè)任務(wù)的數(shù)據(jù)進(jìn)來,這就是線程上下問的切換

java 的這種多線程機(jī)制由于涉及線程的上下文操作會(huì)帶來一個(gè)性能問題,線程的上下文切換和線程對(duì)象的創(chuàng)建是很消耗資源的

2個(gè)加減法循環(huán)在串行和并行時(shí)的性能對(duì)比,只有在百萬(wàn)次時(shí)他們的性能在相容,百萬(wàn)次以下,并行沒有性能上的優(yōu)勢(shì),所以在 rxjava 的線程池線程設(shè)計(jì)在大型就算任務(wù)時(shí),線程池線程數(shù)量 =cpu 內(nèi)核數(shù),io 等非計(jì)算耗時(shí)任務(wù)時(shí)線程池線程數(shù)量無顯示


那么如何減少上下文切換:

  • 無鎖并發(fā)編程
    無鎖并發(fā)編程.當(dāng)任何特定的運(yùn)算被阻塞的時(shí)候,所有CPU可以繼續(xù)處理其他的運(yùn)算。換種方式說,在無鎖系統(tǒng)中,當(dāng)給定線程被其他線程阻塞的時(shí)候,所有CPU可以不停的繼續(xù)處理其他工作。無鎖算法大大增加系統(tǒng)整體的吞吐量,因?yàn)樗慌紶枙?huì)增加一定的交易延遲。大部分高端數(shù)據(jù)庫(kù)系統(tǒng)是基于無鎖算法而構(gòu)造的,以滿足不同級(jí)別
  • CAS 算法
    Java提供了一套原子性操作的數(shù)據(jù)類型(java.util.concurrent.atomic包下),使用CAS算法來更新數(shù)據(jù),不需要加鎖。如:AtomicInteger、AtomicLong等
  • 使用最少線程
    避免創(chuàng)建不需要的線程,比如任務(wù)很少,但是創(chuàng)建了很多線程來處理,這樣會(huì)造成大量線程都處于等待狀態(tài)
  • 協(xié)程
    在單線程里實(shí)現(xiàn)多任務(wù)的調(diào)度,并在單線程里維持多個(gè)任務(wù)間的切換,kotlin ,goland 都支持協(xié)程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。