volatile與synchronized的區別與做用

做用:

volatile修飾的變量可以保證全部線程的可見性,即當數據修改後全部線程都可以訪問到修改後的數據安全

synchronized同步鎖,表示在多線程環境下只能有一個線程進入被synchronized修飾過的代碼塊、方法、變量、對象。多線程

區別:

修飾對象不一樣,volatile只能修飾於變量,而synchronized能夠修飾代碼塊、方法、變量、對象線程

volatile保證了可見性和有序性,synchronized保證了原子性對象


volatile的可見性

每一個線程從本身線程獨佔的cache取數據,而cache經過JMM取到在主存上的數據,而這些數據通訊由JVM控制,線程間不能直接通訊,何時將數據同步到主存,何時從主存取數據都要靠JVMblog

image-20210813140953382

那麼這種模型在多線程模型中保證了安全,可是效率低下編譯器

而volatile的原理是將volatile修飾的變量在修改後強制同步到主存,而且每次使用這個數據都要去主存中更新同步

當保證了變量的可見性後,在編譯器和CPU級別上都會由於Memory Barrier指令禁止指令重排編譯

synchronized原理

在jdk1.6以前,synchronized一直都是重量級鎖,1.6以後引入了偏向鎖、輕量級鎖,如今對象就有了四個狀態:無鎖、偏向鎖、輕量級鎖、重量級鎖效率

image-20210813143226654

四種狀態實現

每一個對象都有對象頭,而對於每一個對象的鎖狀態都是在對象頭上的markword上變量

image-20210813143756513

當線程進入同步區域時,若是同步對象的對象頭鎖標誌位爲"01"則表示可進入,進入後將標誌位設置爲"00"表示這個線程得到了鎖,而且將這個對象設置輕量級鎖鎖定狀態,若是這個更新操做失敗,而且檢測是否有多個線程在競爭當前鎖,若是有多個線程競爭則會轉換爲重量級鎖而且使其餘線程阻塞,而當前線程則自旋等待。

當線程請求到鎖時,將鎖對象的標誌位改成"01",而後將線程的ID記錄到MarkWord中,之後該線程將能夠直接進入該同步區域,可是若是有其餘線程請求鎖,將會當即轉換爲輕量級鎖模式。

無鎖、偏向鎖、輕量級鎖、重量級鎖狀態切換

image-20210813151538409

相關文章
相關標籤/搜索