【基礎知識點】Synchronized、volatile與ThreadLocal區別及使用場景

1.Synchronized

Synchronized關鍵字保證了數據讀寫一致和可見性等問題,但是他是一種阻塞的線程控制方法,在關鍵字使用期間,所有其他線程不能使用此變量。(同步機制採用了“以時間換空間”的方式)

修飾一個類

class ClassName {
    public void method() {
       synchronized(ClassName.class) {
          // todo
       }
    }
 }

修飾一個方法

public synchronized void method()
{
   // todo
}

修飾一個代碼塊

public  void method()
{
   synchronized(this){
   ......
   }
}

修飾一個靜態的方法

public synchronized static void method() {
   // todo
}

2.volatile

volatile如何實現可見性?

volatile變量每次被線程訪問時,都強迫線程從主內存中重讀該變量的最新值,而當該變量發生修改變化時,也會強迫線程將最新的值刷新回主內存中。這樣一來,不同的線程都能及時的看到該變量的最新值。

但是volatile不能保證變量更改的原子性:

比 如number++,這個操作實際上是三個操作的集合(讀取number,number加1,將新的值寫回number),volatile只能保證每一 步的操作對所有線程是可見的,但是假如兩個線程都需要執行number++,那麼這一共6個操作集合,之間是可能會交叉執行的,那麼最後導致number 的結果可能會不是所期望的。

所以對於number++這種非原子性操作,推薦用synchronized:

synchronizedthis{
     number++;   
}

3.synchronized和volatile比較

  1. volatile不需要同步操作,所以效率更高,不會阻塞線程,但是適用情況比較窄

  2. volatile讀變量相當於加鎖(即進入synchronized代碼塊),而寫變量相當於解鎖(退出synchronized代碼塊)

  3. synchronized既能保證共享變量可見性,也可以保證鎖內操作的原子性;volatile只能保證可見性

4.ThreadLocal

ThreadLocal不是爲了解決多線程訪問共享變量,而是爲每個線程創建一個單獨的變量副本,提供了保持對象的方法和避免參數傳遞的複雜性。

顧名思義它是local variable(線程局部變量)。它的功用非常簡單,就是爲每一個使用該變量的線程都提供一個變量值的副本,是每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本衝突。從線程的角度看,就好像每一個線程都完全擁有該變量。(ThreadLocal採用了“以空間換時間”的方式)

參考資料

Java—線程多(工作內存)和內存模型(主內存)分析

Java多線程共享變量控制

使用synchronized的幾種場景

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