java多線程(一)---上下文切換

1. 上下文切換的概念

  • CPU通過(guò)時(shí)間片分配算法來(lái)循環(huán)執(zhí)行任務(wù),當(dāng)前任務(wù)執(zhí)行一個(gè)時(shí)間片后會(huì)切換到下一個(gè)任務(wù)。
  • 在切換前會(huì)保存上一個(gè)任務(wù)的狀態(tài),以便下次切換回這個(gè)任務(wù)時(shí),可以再加載這個(gè)任務(wù)的狀態(tài)。
  • 所以任務(wù)從保存到再加載的過(guò)程就是一次上下文切換
  • 即使是單核處理器也支持多線程執(zhí)行代碼,CPU通過(guò)給每個(gè)線程分配CPU時(shí)間片來(lái)實(shí)現(xiàn)這個(gè)機(jī)制。
  • 時(shí)間片是CPU分配給各個(gè)線程的時(shí)間,因?yàn)闀r(shí)間片非常短,所以CPU通過(guò)不停地切換線程執(zhí)行,讓我們感覺(jué)多個(gè)線程是同時(shí)執(zhí)行的,時(shí)間片一般是幾十毫秒(ms)。

2. 多線程一定快嗎

示例:

public class ConcurrencyTest {
    private static final long count = 10000l;
    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();
    }
    
    //并發(fā)
    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--;
        }
        long time = System.currentTimeMillis() - start;
        thread.join();
        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);
    }
}
Screenshot_20180723_185057.jpg
  • 當(dāng)并發(fā)執(zhí)行累加操作不超過(guò)百萬(wàn)次時(shí),速度會(huì)比串行執(zhí)行累加操作要慢。
  • 這是因?yàn)榫€程有創(chuàng)建和上下文切換的開(kāi)銷。

3 如何減少上下文切換

減少上下文切換的方法有無(wú)鎖并發(fā)編程、CAS算法、使用最少線程使用協(xié)程。

  • 無(wú)鎖并發(fā)編程。
    多線程競(jìng)爭(zhēng)鎖時(shí),會(huì)引起上下文切換,所以多線程處理數(shù)據(jù)時(shí),可以用一些辦法來(lái)避免使用鎖,如將數(shù)據(jù)的ID按照Hash算法取模分段,不同的線程處理不同段的數(shù)據(jù)。
  • CAS算法。
    Java的Atomic包使用CAS算法來(lái)更新數(shù)據(jù),而不需要加鎖。
  • 使用最少線程。
    避免創(chuàng)建不需要的線程,比如任務(wù)很少,但是創(chuàng)建了很多線程來(lái)處理,這樣會(huì)造成大量線程都處于等待狀態(tài)。
  • 協(xié)程
    在單線程里實(shí)現(xiàn)多任務(wù)的調(diào)度,并在單線程里維持多個(gè)任務(wù)間的切換。

參考

《java并發(fā)編程的藝術(shù)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 0 前言 在過(guò)去單CPU時(shí)代,單任務(wù)在一個(gè)時(shí)間點(diǎn)只能執(zhí)行單一程序。之后發(fā)展到多任務(wù)階段,計(jì)算機(jī)能在同一時(shí)間點(diǎn)并行執(zhí)...
    七寸知架構(gòu)閱讀 10,004評(píng)論 6 95
  • 1、背景 并發(fā)編程的目的是為了讓程序運(yùn)行得更快,但是并不是啟動(dòng)更多的線程就能讓程序最大 限度地并發(fā)執(zhí)行。在進(jìn)行并發(fā)...
    maerzi閱讀 366評(píng)論 0 2
  • 一、CPU時(shí)間片 CPU時(shí)間片即CPU分配給每個(gè)線程的執(zhí)行時(shí)間段,稱作它的時(shí)間片。CPU時(shí)間片一般為幾十毫秒(ms...
    barry_di閱讀 6,728評(píng)論 0 1
  • 多線程的代價(jià) --------------------------------------------------...
    小陳阿飛閱讀 1,543評(píng)論 0 0
  • 青春是什么樣的?或許我們每一個(gè)人都相似而不同著。 我的青春、我的十七歲沒(méi)有一個(gè)住在心底的男孩,沒(méi)有電影里的妥協(xié)和墮...
    歧得閱讀 503評(píng)論 0 0

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