Java基礎之synchronized & volatile

b站地址:https://www.bilibili.com/video/BV1tz411q7c2
https://www.bilibili.com/video/BV1xK4y1C7aT?from=search&seid=2269221721031516085

synchronized & volatile

問題如下

在這裏插入圖片描述

需要學習的知識

在這裏插入圖片描述

CAS

在這裏插入圖片描述

追查源碼,最終到jvm的unsafe.cpp下,
在這裏插入圖片描述
而sychronized 輕量級鎖實現是cas,底層是lock ;cmpxchg指令。cmpxchg硬件底層指令是沒用原子性的,也就是說,可能在更新值得過程中將其他的線程更新值覆蓋,但是加上lock表示,不允許其他cpu的相關操作。
volatile則底層是lock; addl.

java對象的組成部分

markword,類指針,對象的屬性,padding

markword包括哪些信息

1.鎖信息,2.GC信息,3.identify hashcode(唯一標識符)

  • 64位
    在這裏插入圖片描述

用代碼查看鎖的信息。

    public static void main(String[] args) throws Exception{
        //sleep(5000);
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
        synchronized (o)
        {
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
    }

打印結果

在這裏插入圖片描述
001表示的是處於無鎖的狀態,後面的000則是偏向鎖。
如果把sleep(5000)註釋打開,即休眠5s。
在這裏插入圖片描述

鎖升級過程

在這裏插入圖片描述

在這裏插入圖片描述

volatile

1.防止指令重排序
2.保證線程可見性

happen-before就是一種規定,這些執行情況 不允許指令重排序。
比如 volatile修飾規則,join規則,線程start規則,傳遞規則,對象鎖規則。
詳情:https://blog.csdn.net/hanchao5272/article/details/79575491
as-if-serial規則就是,當發生指令重排時,必須保證,和串行發生一樣。

在這裏插入圖片描述
load就是讀,store就是寫。
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
JVM層面看的話,是加了 ACC_VOLATILE,設定對volatile修飾的變量需要前後加內存屏障再訪問或者修改,
屏障的底層是是通過 lock ; addl 指令(編譯語言層面)實現,意思可以理解爲暫時鎖住總線,不允許其他的線程直接訪問內存,總之就是保證讀到的內存數據是一致的,寫可以導致其他高速緩衝區數據失效,讀屏障可以要求cpu去內存讀。

超線程

在這裏插入圖片描述

引用類型

強引用,比如Object o = new Object();,o指向堆中的Object對象,o就是強引用,垃圾回收時一定不會進行回收。
軟引用:在內存不足時回收
弱引用:每次垃圾回收都會進行回收。
虛引用:用於堆外的內存回收。
https://www.cnblogs.com/gudi/p/6403953.html
在ThreadLocal中使用的就是弱引用,大致的圖結構如下:
代碼:
在這裏插入圖片描述
注意使用完需要調用remove方法,防止內存泄漏。
大致結構:

在這裏插入圖片描述
使用弱引用的原因是防止內存泄漏,key是一個ThreadLocal對象 ,每次set的時候就new一個繼承了WeakReference的Entry,並且將key傳給父類(WeakReference),使一個弱引用指向ThreadLocal對象,當tl引用消失,垃圾回收時就會自動回收ThreadLocal對象,但是在ThreadLocalMap中的值不會消失,所以爲了防止內存泄露,需要再次調用remove方法。

書籍推薦

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章