多线程与高并发(二):解析自旋锁CAS操作与volatile
生活随笔
收集整理的這篇文章主要介紹了
多线程与高并发(二):解析自旋锁CAS操作与volatile
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Volitile 作用:保證線程的可見性,同時禁止指令的重排序
多線程時,存在的問題在于,在一個線程中對副本的更改并沒有及時地反映到另外一個線程中。這就是線程之間的不可見。
對變量值加了 volitile 之后,一個線程中的改變,在另一個線程中可以立刻看到。
volatile 關鍵字,使一個變量在多個線程間可見,示例:
餓漢單例模式
package com.mashibing.dp.singleton;/*** 餓漢式* 類加載到內存后,就實例化一個單例,JVM保證線程安全* 簡單實用,推薦使用!* 唯一缺點:不管用到與否,類裝載時就完成實例化* Class.forName("")* (話說你不用的,你裝載它干啥)*/ public class Mgr01 {private static final Mgr01 INSTANCE = new Mgr01();private Mgr01() {};public static Mgr01 getInstance() {return INSTANCE;}public void m() {System.out.println("m");}public static void main(String[] args) {Mgr01 m1 = Mgr01.getInstance();Mgr01 m2 = Mgr01.getInstance();System.out.println(m1 == m2);} }懶漢單例模式
package com.mashibing.dp.singleton;/*** lazy loading* 也稱懶漢式* 雖然達到了按需初始化的目的,但卻帶來線程不安全的問題* 可以通過synchronized解決,但也帶來效率下降*/ public class Mgr06 {private static volatile Mgr06 INSTANCE; //JITprivate Mgr06() {}public static Mgr06 getInstance() {if (INSTANCE == null) {//雙重檢查synchronized (Mgr06.class) {if(INSTANCE == null) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}INSTANCE = new Mgr06();}}}return INSTANCE;}public void m() {System.out.println("m");}public static void main(String[] args) {for(int i=0; i<100; i++) {new Thread(()->{System.out.println(Mgr06.getInstance().hashCode());}).start();}} }面試題:你聽說過單例模式嗎?單例模式里面有一種叫雙重檢查的你了解嗎?這個單例要不要加volitile?
CAS
AtomicInteger
如何解決ABA問題?
基礎數據類型即使出現了ABA,一般問題不大。
如果是一個Object,紅色對象指向黃色對象,黃色對象指向藍色對象。現在,紅色對象偷偷指向藍色對象,將藍色對象里的內容改變,再偷偷指回黃色對象,而黃色對象沒有察覺到紅色對象的ABA改變導致藍色對象的改變,這時候黃色對象后面的業務邏輯是不是還和原來保持一樣,這就不好說了~
解決方式:加版本號,后面檢查的時候連版本號一起檢查
Atomic里面有帶版本號的類AtomicStampedReference,目前還沒有人在面試的時候遇到過。
不需要加鎖是怎么做到的呢?原因是使用了Unsafe這個類,Unsafe類是個單例,這個類可以直接申請內存、釋放內存
JDK11做了一些大的改動,下圖是1.7版本時的Unsafe類。
總結
以上是生活随笔為你收集整理的多线程与高并发(二):解析自旋锁CAS操作与volatile的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络与IO知识扫盲(七):仿照Netty
- 下一篇: JVM从入门到精通(一):JVM入门级c