感謝大佬的錄屏,延遲看一下JVM的視訊課程,記一下筆記:
開篇這玩意兒我暫時也看不懂,先放在這裡:

接下來給了一段建立對象的代碼,以及它的java彙編碼
位元組碼:
0.new ->申請記憶體。堆裡有了一個新的記憶體。(半初始化。成員變量設定預設值)
3 dup 因為invokespecial會消耗一份,是以必須先複制一份
4 invokespecial T initlize 初始化,調用他的構造方法
7 astore_1 把t與T建立關聯
8 return
那麼上圖的第一個問題就解決了。看第二個問題。DCL與violatile
設計模式:單例:new Class時候,隻要求記憶體中隻能new出一個對象。
裡面調getInstance永遠隻有一個對象
或者:
上來先判斷,if instance為空再new出來。(多線程通路的時候并不安全,多線程可能會new多個instance)
是以如果有多線程通路時:在方法加synchronize。永遠隻有一個線程通路:但是整個方法全上鎖了,沒考慮業務内容是否也需要被鎖
如果為空,再上鎖。但卡的位置不對,第一個線程還沒來得及new,第二個線程又來了,還是空,那第二個線程也new。是以不合适
是以!!DCL:
先上鎖,再判空。檢查兩遍double check lock DCL 單例寫法
單例前面是否要加 violatile:
1.保持線程可見性
2.禁止指令重排序 (本來CPU多條流水線執行)
DCL單例情況下重排序:
發生指令重排序後,使m初始化後,m不為空。此時thread2直接拿到m=0了。
是以必須要加volatile禁止指令重排序!對m這個對象的記憶體區域加volatile,對這塊區域的讀寫都要加memory barrier
3.對象在記憶體中的存儲布局
(markword标記字 8位元組/class pointer類型指針 4位元組)
統稱為對象頭。上圖訂正。
總長度要能被8整除,提高效率,是以後面會有個對齊 (計算機總線,cpu總線,寄存器,最好都是8個位元組往裡扔)
對象上鎖後的變化(是以能看出markword裡面有鎖資訊)
以下鎖狀态全部記錄在markword裡面
偏向鎖:biased lock: JVM認為大多數情況下這把鎖也就一個線程在用,當第一個線程過來的時候,沒有必要上鎖,就把名片往上面一貼。奧利給!那麼這個坑就是你的,上面貼着你的名片,再來點時候也不需要競争。
偏向鎖 沒有鎖競争的過程,上鎖很快,效率很高
當特朗普看到上面有奧利給的名字,那麼就有鎖競争了。先把奧利給名片扯下來,通過CAS的方式,往上貼名片,誰貼上去這個坑就是誰的。
CAS:(無鎖狀态)
比如說線程要給記憶體中的0進行+1操作,如果不加鎖的話,就先将這個數字讀出來,再在記憶體中做計算,再把這個1往回寫。
寫的時候檢查記憶體中的0是否還是0,如果還是0,就直接寫入1。
但如果記憶體中不是0,是1了,那就讀1,回去重新計算+1,再往回寫2
這種方法不用加鎖,但存在AB A問題。怎麼解決?加入版本号
CAS設定lock record。奧利給在裡面憋着幹活,特朗普在外面急着轉圈,自旋,讀标簽。
自旋鎖:當旋轉次數超過cpu核數的1/2,會更新到最後的重量級鎖 (java5.0前)算法
後面更新到自适應自旋,就是旋轉次數不進行設定,由JVM自适應設定,看是否需要更新重量級鎖,向作業系統老大申請資源。
輕量級鎖 lock-free:
重量級鎖:要向作業系統申請鎖資源。JVM對應線程放進這把鎖的等待隊列裡,什麼時候輪到你,什麼時候執行。(旋轉的人太多,把你冷凍了。讓這些搶不到鎖的線程不會消耗cpu)
以上所有的鎖都是互斥鎖
截止obj.mp4視訊 65:14
5.6.7今天先不看了待續