日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...

發布時間:2023/12/10 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 安全性問題

  • 線程安全的本質是正確性,而正確性的含義是程序按照預期執行
  • 理論上線程安全的程序,應該要避免出現可見性問題(CPU緩存)、原子性問題(線程切換)和有序性問題(編譯優化)
  • 需要分析是否存在線程安全問題的場景:存在共享數據且數據會發生變化,即有多個線程會同時讀寫同一個數據
  • 針對該理論的解決方案:不共享數據,采用線程本地存儲(Thread Local Storage,TLS);不變模式
  • Ⅰ. 數據競爭

    數據競爭(Data Race):多個線程同時訪問同一數據,并且至少有一個線程會寫這個數據

    1. add

    private static final int MAX_COUNT = 1_000_000;private long count = 0;// 非線程安全public void add() { int index = 0; while (++index < MAX_COUNT) { count += 1; }}

    2. add + synchronized

    private static final int MAX_COUNT = 1_000_000;private long count = 0;public synchronized long getCount() { return count;}public synchronized void setCount(long count) { this.count = count;}// 非線程安全public void add() { int index = 0; while (++index < MAX_COUNT) { setCount(getCount() + 1); }}
    • 假設count=0,當兩個線程同時執行getCount(),都會返回0
    • 兩個線程執行getCount()+1,結果都是1,最終寫入內存是1,不符合預期,這種情況為竟態條件

    Ⅱ. 竟態條件

  • 竟態條件(Race Condition):程序的執行結果依賴于線程執行的順序
  • 在并發環境里,線程的執行順序是不確定的
    • 如果程序存在竟態條件問題,那么意味著程序的執行結果是不確定的

    1. 轉賬

    public class Account { private int balance; // 非線程安全,存在竟態條件,可能會超額轉出 public void transfer(Account target, int amt) { if (balance > amt) { balance -= amt; target.balance += amt; } }}

    Ⅲ. 解決方案

    面對數據競爭和竟態條件問題,可以通過互斥的方案來實現線程安全,互斥的方案可以統一歸為鎖

    二. 活躍性問題

    活躍性問題:某個操作無法執行下去,包括三種情況:死鎖、活鎖、饑餓

    Ⅰ. 死鎖

  • 發生死鎖后線程會相互等待,表現為線程永久阻塞
  • 解決死鎖問題的方法是規避死鎖(破壞發生死鎖的條件之一)
    • 互斥:不可破壞,鎖定目的就是為了互斥
    • 占有且等待:一次性申請所有需要的資源
    • 不可搶占:當線程持有資源A,并嘗試持有資源B時失敗,線程主動釋放資源A
    • 循環等待:將資源編號排序,線程申請資源時按遞增(或遞減)的順序申請

    Ⅱ. 活鎖

    • 活鎖:線程并沒有發生阻塞,但由于相互謙讓,而導致執行不下去
    • 解決方案:在謙讓時,嘗試等待一個隨機時間(分布式一致算法Raft也有采用)

    Ⅲ. 饑餓

  • 饑餓:線程因無法訪問所需資源而無法執行下去
    • 線程的優先級是不相同的,在CPU繁忙的情況下,優先級低的線程得到執行的機會很少,可能發生線程饑餓
    • 持有鎖的線程,如果執行的時間過長(持有的資源不釋放),也有可能導致饑餓問題
  • 解決方案
    • 保證資源充足
    • 公平地分配資源(公平鎖) – 比較可行
    • 避免持有鎖的線程長時間執行

    三. 性能問題

  • 鎖的過度使用可能會導致串行化的范圍過大,這會影響多線程優勢的發揮(并發程序的目的就是為了提升性能)
  • 盡量減少串行,假設串行百分比為5%,那么多核多線程相對于單核單線程的提升公式(Amdahl定律)
  • S=1/((1-p)+p/n),n為CPU核數,p為并行百分比,(1-p)為串行百分比
    • 假如p=95%,n無窮大,加速比S的極限為20,即無論采用什么技術,最高只能提高20倍的性能

    Ⅰ. 解決方案

  • 無鎖算法和數據結構
    • 線程本地存儲(Thread Local Storage,TLS)
    • 寫入時復制(Copy-on-write)
    • 樂觀鎖
    • JUC中的原子類
    • Disruptor(無鎖的內存隊列)
  • 減少鎖持有的時間,互斥鎖的本質是將并行的程序串行化,要增加并行度,一定要減少持有鎖的時間
    • 使用細粒度鎖,例如JUC中的ConcurrentHashMap(分段鎖)
    • 使用讀寫鎖,即讀是無鎖的,只有寫才會互斥的

    Ⅱ. 性能指標

  • 吞吐量:在單位時間內能處理的請求數量,吞吐量越高,說明性能越好
  • 延遲:從發出請求到收到響應的時間,延遲越小,說明性能越好
  • 并發量:能同時處理的請求數量,一般來說隨著并發量的增加,延遲也會增加,所以延遲一般是基于并發量來說的
  • 寫在最后

    • 第一:看完點贊,感謝您的認可;
    • ...
    • 第二:隨手轉發,分享知識,讓更多人學習到;
    • ...
    • 第三:記得點關注,每天更新的!!!
    • ...

    總結

    以上是生活随笔為你收集整理的并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。