0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳析Java線程進(jìn)程的并發(fā)問題

如意 ? 來源:IT技術(shù)百貨 ? 作者:IT技術(shù)百貨 ? 2020-07-07 11:44 ? 次閱讀

并發(fā)的前提條件

并發(fā)問題發(fā)生的前提條件一定是資源共享,這里的資源一般指的是數(shù)據(jù),共享指的是多線程之間共享。

也就是只有在多線程共享資源的情況下才可能產(chǎn)生并發(fā)問題,這是并發(fā)問題產(chǎn)生的前提條件,在這個條件下,有可能產(chǎn)生并發(fā)問題,那么并發(fā)問題的根源究竟是什么呢?

CPU操作數(shù)據(jù)的基本機(jī)制

前面提到了并發(fā)的前提條件是數(shù)據(jù)共享,想了解并發(fā)問題的根源就需要知道CPU操作數(shù)據(jù)的基本原理;

數(shù)據(jù)存儲包括這幾個位置:磁盤、內(nèi)存、緩存、寄存器;

寄存器可以認(rèn)為是CPU的一部分,所以有的地方并沒有將CPU和寄存器拆分講解,通常來講只需要知道CPU運(yùn)算時都是從寄存器取數(shù)據(jù),運(yùn)算完成后再放回寄存器即可,CPU和寄存器之間沒有其他任何中介。

緩存是CPU與寄存器之外的一層存儲,但也是每一個CPU獨(dú)立占有的一塊內(nèi)存區(qū)域,各個CPU緩存之間數(shù)據(jù)不可以共享。

內(nèi)存是程序運(yùn)行時數(shù)據(jù)的主要存放區(qū)域,內(nèi)存數(shù)據(jù)是共享的,一般來講,各個CPU都可以訪問內(nèi)存中的數(shù)據(jù);

磁盤,數(shù)據(jù)最終持久化的存儲;

CPU操作數(shù)據(jù)的流程一般是先由磁盤讀到內(nèi)存,再從內(nèi)存讀到緩存,再由緩存到寄存器進(jìn)行運(yùn)算;運(yùn)算之后的結(jié)果直接寫入寄存器,然后刷新到緩存,再刷新到內(nèi)存,最后寫入磁盤;

程序數(shù)據(jù)流圖

并發(fā)問題的源頭

了解了CPU運(yùn)行機(jī)制之后,下面說并發(fā)問題的根源,主要是由于數(shù)據(jù)可見性、操作原子性、操作有序性這三個原因?qū)е碌模?/p>

什么是數(shù)據(jù)可見性?

通俗點來說就是CPU看到的數(shù)據(jù)并不是最新的數(shù)據(jù),CPU讀取數(shù)據(jù)是優(yōu)先從緩存中讀取,如果緩存中存在就使用緩存中的數(shù)據(jù),假如數(shù)據(jù)被另一個CPU改變了,這時其他CPU中緩存數(shù)據(jù)就可能與內(nèi)存中的數(shù)據(jù)不一致,也就是CPU沒有看到并使用最新的數(shù)據(jù),導(dǎo)致程序執(zhí)行結(jié)果異常。

什么是操作原子性?

同一個CPU可以交替執(zhí)行多個線程,不太了解的讀者可以初步學(xué)習(xí)一下CPU時間片與線程調(diào)度的基本知識。

在同一個CPU,交替執(zhí)行多個線程的時候,就可能出現(xiàn)線程中斷,并且在中斷過程中受其他線程影響而導(dǎo)致中斷的線程恢復(fù)之后,執(zhí)行邏輯異常。

比如:a線程執(zhí)行count = count + 1操作,b線程也執(zhí)行相同的操作;當(dāng)a線程讀取到count的值,并進(jìn)行加1計算之后,還沒寫回到內(nèi)存之前被中斷,b線程完全執(zhí)行了count = count + 1,count的值得到更新;這時a線程恢復(fù)(并不會重新讀取并計算),將之前計算的值寫回到緩存,導(dǎo)致count本來應(yīng)該執(zhí)行兩次加1,但最終結(jié)果只加了一次1;

什么是操作有序性?

有序性指的是CPU執(zhí)行代碼的順序和程序開發(fā)者定義的順序不一致?為什么還會不一致呢?

編譯器在將高級開發(fā)語言編譯成計算機(jī)指令的時候,出于性能優(yōu)化,可能會對代碼執(zhí)行重排序,CPU在執(zhí)行指令的時候,也可能對代碼重排序;當(dāng)然重排序的前提是在單線程條件下的語義不變性,但不能保證多線程條件下語義也相同。

Java單例模式中的雙重校驗鎖,單例變量為什么要聲明為volatile,就是為了解決指令重排序帶來的問題,我們在下一章節(jié)進(jìn)行詳細(xì)講解。感興趣的也可以自行查閱資料學(xué)習(xí)。

并發(fā)問題的解決方案

并發(fā)問題不是Java語言特有的,而是計算機(jī)運(yùn)行原理與操作系統(tǒng)帶來的,那么從計算機(jī)與操作系統(tǒng)層面來看,它們都提供了哪些解決方案來避免數(shù)據(jù)可見性、程序原子性、操作有序性的保障呢?Java語言又是如何對這些方案進(jìn)行封裝的呢?開發(fā)者有哪些手段可以解決這些問題呢?

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2973

    瀏覽量

    104913
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    505

    瀏覽量

    19715
  • 進(jìn)程
    +關(guān)注

    關(guān)注

    0

    文章

    204

    瀏覽量

    13971
收藏 人收藏

    評論

    相關(guān)推薦

    socket 多線程編程實現(xiàn)方法

    是指在同一個進(jìn)程中運(yùn)行多個線程,每個線程可以獨(dú)立執(zhí)行任務(wù)。線程共享進(jìn)程的資源,如內(nèi)存空間和文件句柄,但每個
    的頭像 發(fā)表于 11-12 14:16 ?423次閱讀

    一文搞懂Linux進(jìn)程的睡眠和喚醒

    機(jī)制 1)信號(Signal): 進(jìn)程可以通過接受特定信號被喚醒。 2)條件變量(Condition Variable): 多線程編程中用于同步多個線程的工具,可以讓一個線程在某些
    發(fā)表于 11-04 15:15

    go語言如何解決并發(fā)問

    作為一個后端開發(fā),日常工作中接觸最多的兩門語言就是PHP和GO了。無可否認(rèn),PHP確實是最好的語言(手動狗頭哈哈),寫起來真的很舒爽,沒有任何心智負(fù)擔(dān),字符串和整型壓根就不用區(qū)分,開發(fā)速度真的是比GO快很多?,F(xiàn)在工作中也還是有一些老項目在使用PHP,但21年之后的新項目基本上就都是用GO了。那為什么PHP那么香,還要轉(zhuǎn)戰(zhàn)使用GO呢,下面就給大家講解一下我們新項目從PHP轉(zhuǎn)GO的原因,有幾個比較重要的點:
    的頭像 發(fā)表于 10-23 13:38 ?157次閱讀
    go語言如何解決<b class='flag-5'>并發(fā)問</b>題

    Python中多線程和多進(jìn)程的區(qū)別

    Python作為一種高級編程語言,提供了多種并發(fā)編程的方式,其中多線程與多進(jìn)程是最常見的兩種方式之一。在本文中,我們將探討Python中多線程與多進(jìn)
    的頭像 發(fā)表于 10-23 11:48 ?447次閱讀
    Python中多<b class='flag-5'>線程</b>和多<b class='flag-5'>進(jìn)程</b>的區(qū)別

    探索虛擬線程:原理與實現(xiàn)

    虛擬線程的引入與優(yōu)勢 在Loom項目之前,Java虛擬機(jī)(JVM)中的線程是通過java.lang.Thread類型來實現(xiàn)的,這些線程被稱為
    的頭像 發(fā)表于 06-24 11:35 ?328次閱讀
    探索虛擬<b class='flag-5'>線程</b>:原理與實現(xiàn)

    動態(tài)線程池思想學(xué)習(xí)及實踐

    相關(guān)文檔 美團(tuán)線程池實踐:https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html 線程池思想解析:https
    的頭像 發(fā)表于 06-13 15:43 ?1217次閱讀
    動態(tài)<b class='flag-5'>線程</b>池思想學(xué)習(xí)及實踐

    一句話讓你理解線程進(jìn)程

    今天給大家分享一下線程進(jìn)程,主要包含以下幾部分內(nèi)容:一句話說明線程進(jìn)程操作系統(tǒng)為什么需要進(jìn)程為什么要引入
    的頭像 發(fā)表于 06-04 08:04 ?1265次閱讀
    一句話讓你理解<b class='flag-5'>線程</b>和<b class='flag-5'>進(jìn)程</b>

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語言基礎(chǔ)類庫多線程并發(fā)概述

    的一系列復(fù)雜偶發(fā)的問題,同時并發(fā)度也相對較高,因此得到了廣泛的支持和使用,也是當(dāng)前ArkTS語言選擇的并發(fā)模型。 由于Actor模型的內(nèi)存隔離特性,所以需要進(jìn)行跨線程的數(shù)據(jù)序列化傳輸。 一、數(shù)據(jù)傳輸
    發(fā)表于 03-28 14:35

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語言基礎(chǔ)類庫多線程并發(fā)概述

    的一系列復(fù)雜偶發(fā)的問題,同時并發(fā)度也相對較高,因此得到了廣泛的支持和使用,也是當(dāng)前ArkTS語言選擇的并發(fā)模型。 由于Actor模型的內(nèi)存隔離特性,所以需要進(jìn)行跨線程的數(shù)據(jù)序列化傳輸。 一、數(shù)據(jù)傳輸
    發(fā)表于 03-22 15:40

    java實現(xiàn)多線程的幾種方式

    Java實現(xiàn)多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執(zhí)行不同的任務(wù)或操作。
    的頭像 發(fā)表于 03-14 16:55 ?765次閱讀

    python中5種線程鎖盤點

    線程安全是多線程或多進(jìn)程編程中的一個概念,在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機(jī)制保證各個
    發(fā)表于 03-07 11:08 ?1643次閱讀
    python中5種<b class='flag-5'>線程</b>鎖盤點

    基于RTOS的應(yīng)用進(jìn)程中的典型線程

    RTOS中的關(guān)鍵因素是最小的中斷延遲和最小的線程切換延遲。RTOS的價值在于它的響應(yīng)速度或可預(yù)測性,而不是它在給定時間段內(nèi)可以執(zhí)行的工作量。
    發(fā)表于 03-05 09:32 ?664次閱讀
    基于RTOS的應(yīng)用<b class='flag-5'>進(jìn)程</b>中的典型<b class='flag-5'>線程</b>

    嵌入式系統(tǒng)中的線程、進(jìn)程與任務(wù)概念與區(qū)別

    每個線程與主程序共用地址空間,受限于2GB地址空間; 2)線程之間的同步和加鎖控制比較麻煩;一個線程的崩潰可能影響到整個程序的穩(wěn)定性
    發(fā)表于 03-04 15:03 ?1423次閱讀
    嵌入式系統(tǒng)中的<b class='flag-5'>線程</b>、<b class='flag-5'>進(jìn)程</b>與任務(wù)概念與區(qū)別

    HarmonyOS如何使用異步并發(fā)能力進(jìn)行開發(fā)

    一、并發(fā)概述 并發(fā)是指在同一時間段內(nèi),能夠處理多個任務(wù)的能力。為了提升應(yīng)用的響應(yīng)速度與幀率,以及防止耗時任務(wù)對主線程的干擾,HarmonyOS系統(tǒng)提供了異步并發(fā)和多
    的頭像 發(fā)表于 02-18 09:18 ?551次閱讀

    線程是什么的基本單位 進(jìn)程線程的本質(zhì)區(qū)別

    的代碼、數(shù)據(jù)以及用于執(zhí)行這些代碼的上下文信息。一個進(jìn)程可以由一個或多個線程組成,從而并發(fā)執(zhí)行多個任務(wù)。 本質(zhì)區(qū)別: 資源擁有方式:進(jìn)程是資源分配的基本單位,每個
    的頭像 發(fā)表于 02-02 16:30 ?980次閱讀