天天看點

并發程式設計挑戰之上下文切換

摘記自:《java 并發程式設計的藝術》

并發程式設計的目的是為了讓程式運作得更快,但是,并不是啟動更多的線程就能讓程式最大限度地并發執行。在進行并發程式設計時,如果希望通過多線程執行任務讓程式運作得更快,會面臨非常多的挑戰,比如上下文切換的問題、死鎖的問題,以及受限手硬體和軟體的資源限制問題。

上下文切換

單核處理器也支援多線程執行代碼,CPU通過給每個線程配置設定CPU時間片來實作這個機制。時間片是CPU配置設定給各個線程的時間,因為時間片非常短,是以CPU通過不停地切換線程執行。讓我們感覺多個線程是同時執行的,時間片一般是幾十毫秒(ms).

CPU通過時間片配置設定算法來循環執行任務,目前任務執行一個時間片後會切換到下一個任務。但是,在切換前會儲存上一個任 務的狀态,以便下次切換回這個任務時,可以再加載這個任務的狀态。是以任務從儲存到再加載的過程就是一次上下文切換。

這就像我們同時讀兩本書。 當我們在讀 一本英文的技術書時, 發現某個單詞不認識. 于是便打開字典,但是在放下英文技術書之前,大腦必須先記件這本書讀到了哪裡, 等查完單詞之後能夠能續讀這本書.這樣的切換是會影響讀書效率的,同樣上下文切換也會影響多線程的執行速度。

package com;

public class ConcurrencyTest {
    private static final long count=100001;

    public static void main(String[] args)throws InterruptedException{
        concurrency();
        serial();
    }

    private  static void concurrency()throws InterruptedException{
        long start=System.currentTimeMillis();
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                int a=0;
                for(long i=0;i<count;i++){
                    a+=5;
                }
            }
        });
        thread.start();
        int b=0;
        for(long i=0;i<count;i++){
            b--;
        }
        thread.join();
        long time=System.currentTimeMillis()-start;
        System.out.println("concurrency:"+time+"ms,b="+b);
    }

    private static void serial(){
        long start=System.currentTimeMillis();
        int a=0;
        for(long i=0;i<count;i++){
            a+=5;
        }
        int b=0;
        for(long i=0;i<count;i++){
            b--;
        }
        long time=System.currentTimeMillis()-start;
        System.out.println("serial:"+time+"ms,b="+b+",a="+a);
    }

}      

測試結果

并發程式設計挑戰之上下文切換
  • 無鎖并發程式設計。多線程競争鎖時,會引起上下文切換,是以多線程處理資料時,可以用一些辦法來避免使用鎖,如将資料的ID按照Hash算法取模分段,不同的線程處理不同段的資料。
  • CAS算法。Java的Atomic包使用CAS算法來更新資料,而不需要加鎖。
  • 使用最少線程。避免建立不需要的線程,比如任務很少,但是建立了很多線程來處理,這樣會造成大量線程都處于等待狀态。WAITING的線程少了,系統上下文切換的次數就會少,因為每一次從WAITTING到RUNNABLE都會進行一次上下文的切換。
  • 協程:在單線程裡實作多任務的排程,并在單線程裡維持多個任務間的切換。

繼續閱讀