1. 程式人生 > >雲析面試講解公開課(如何提升offer命中率)2018-12-23

雲析面試講解公開課(如何提升offer命中率)2018-12-23

集合相關

  1. 集合相關異常,以及使用各集合間的優缺點?
  • 臨時解決方案:百度、諮詢同事、快速界解決問題,避免影響專案進度;
  • 解決後的問題反思:
    ArrayList是單執行緒,非執行緒安全,需要手動加鎖實現同步lock或sychornized;因為程式碼不方便重用,CopyOnWriteArrayList,它底層是:寫加鎖,ReentrantLock,讀不加鎖;ReentrantLock,基於AQS同步,它的公平鎖和非公平鎖AQS的基礎又是CAS區別ReentrantLock和sychornized
    ,和jdk關鍵字優化有關。
    CopyOnWriteArrayList底層陣列由volatile修飾,保證記憶體可見性,這裡涉及到重排序happen-beforeCAS記憶體屏障注意原子型別,底層就是volatile修飾的。CAS類似資料庫中的樂觀鎖
    CopyOnWriteArrayList的使用場景:讀多寫少的場景,避免大量臨時陣列產生(因為每次寫的時候,需要兩個陣列,寫操作併發高,導致新生代產生大量臨時陣列,需要大量GC)、黑/白名單(利用分散式Nginx實現ip黑名單,限流,負載均衡,反爬蟲),同包下還有ConcurrentHashMap7與8的Hashmap和ConcurrentHashMap區別

保證思路連續性

  • 一些常見問題:ArrayList的坑、集合優缺點、集合中常見異常、ArrayList能不能在多執行緒中使用
    ConcurrentModificationException併發修改異常產生於iterator迭代遍歷ArrayList,刪除一個元素,產生異常,for/foreach也是,expectedModCount表示修改次數期望值,初始值與modCount相等,但是修改集合成員時,modCount會變化,當兩者不相等是,丟擲這個異常所以需要移除時不能使用list.remove(xxx),而是使用iterator.remove(),因為這個方法會設定那兩個引數相等。

說出在什麼場景下出現異常(發現問題能力)、說出異常原因(分析問題能力)、說出解決方案(解決問題能力)、對一個小問題的擴充套件和延伸(總結問題能力)
示例:發現問題——ArrayList遍歷出現異常、分析問題——找到原始碼原因、解決問題——使用迭代器remove方法可以避免、總結問題——多執行緒場景下迭代器remove方法產生問題引出併發容器
引出CopyOnWriteArrayList,在檢視mysql驅動程式類的時候Driver中發現的

  • 專案中的例子:
  1. CopyOnWriteArrayList原理
  • java.util.concurrent包、字面意思write寫操作需要copy、任何可變操作(add,set,remove等操作)伴隨複製動作
  • 原始碼淺析
    新增元素——add(E e)
lock.lock();  //加鎖,保證執行緒安全
Arrays.copyOf();  //拷貝出新陣列 private volatile transient Object[] array;
lock.unlock();  //finally中解鎖,防止出現異常導致鎖不釋放
/**
* 大致流程都是 先lock一下保證執行緒安全,拷貝出新陣列,操作,修改原陣列引用指向新陣列,unlock解鎖
* 高併發讀請求,走的是舊陣列。
*/
  1. CopyOnWriteArrayList面試關鍵點
  • 寫時複製機制
  • 寫操作加鎖/解鎖
  • 讀操作不需要幾所
  • 體現讀寫分離的思想
  • 體現最終一致性思想
  • 在JDBC驅動程式原始碼中廣泛使用
  • 使用場景:讀多寫少場景——黑名單、白名單、商品類目
  1. 延伸至 volatile關鍵字
    volatile是保證執行緒記憶體可見性 ,區別於加鎖。
    volatile通過JVM底層一些指令,例如:happen-before規則,記憶體屏障等技術,保證cpu0放入到memory記憶體中,執行jvm中指令,強制硬體層面上,其他cpu的cache快取為無效狀態,強制從memory中獲取新值,放到各自的快取中進行計算。"大致是清其他cpu快取,再重新拿快取"

  2. 延伸至 CAS原子型別操作
    CAS(Compare and Swap)
    原子型別:保證操作都是執行緒安全的。
    例如:AtomicInteger 底層有一個 private volatile int value; //實際就是int + volatile修飾

  • CAS有三個運算元
    記憶體值V舊的預期值A要修改的新值B
    當且僅當預期值A和記憶體值V相同時,將記憶體值V修改為B,否則什麼都不做。
  1. 延伸至 樂觀鎖
  2. 延伸至 鎖
    Synchronized是依賴於JVM實現的(作業系統實現)、ReentrantLock是JDK實現的(開發者實現)、兩者效能相當
  • 常見的ReentrantLock 重入鎖:同一時間,只有一個執行緒可以使用臨界資源;公平鎖是若是同一執行緒競爭資源,是可以加上鎖的,先來後到;非公平鎖,後續執行緒沒有按照佇列形式來拿到鎖。
    圖

在多執行緒高併發環境下,多執行緒競爭鎖,有一個競爭成功加上鎖,成功的執行緒直接執行方法邏輯;
加鎖失敗,生成阻塞佇列,存放所有等待執行緒,等待獲取釋放鎖後的使用權;當前一個使用者釋放鎖, 佇列會喚醒一個執行緒去競爭資源加鎖,以達到執行緒安全的效果;成功就加鎖,失敗就再回到阻塞佇列。

  1. sychornized 和 volatile關鍵字

volatile是輕量級的synchronized。鎖提供了兩種特性,互斥和可見性。因此在保證多執行緒讀寫時資料的一致性,可以使用同步即synchronized關鍵字和可見性即volatile。

1.volatile

可見性的意思即當一個執行緒修改了共享變數時,另一個執行緒也能讀取到這個最新的數值。

對於volatile修飾的變數在進行寫操作時,處理器不會直接和記憶體通訊,會先寫入到快取中。在這個寫入快取的過程中,用到快取一致性確保修改的原子性。當快取回寫到記憶體中時會導致其他處理器對此變數的快取無效,會重新讀取此變數的值。

2.synchronized和volatile的區別

1)volatile本質是在告訴jvm當前變數在暫存器中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當前變數,只有當前執行緒可以訪問該變數,其他執行緒被阻塞住.
2)volatile僅能使用在變數級別,synchronized則可以使用在變數,方法.
3)volatile僅能實現變數的修改可見性,而synchronized則可以保證變數的修改可見性和原子性.
4)volatile不會造成執行緒的阻塞,而synchronized可能會造成執行緒的阻塞.

網際網路公司常見架構

圖