為什麼要這樣寫final ReentrantLock lock = this.lock; ?

朱清震發表於2018-03-04

今天JVMPocket天方夜譚群裡的一個朋友問了個問題,為什麼CyclicBarrier的程式碼要這樣寫:

 final ReentrantLock lock = this.lock;
 lock.lock;

其實如果閱讀過java.util.concurrent包下原始碼的童鞋會發現,不止CyclicBarrier原始碼是這樣做的,這個包下,所有以final修飾的成員變數讀取的程式碼大部分情況都是這樣寫的,大部分指情況的是:

  1. 全部的迴圈程式碼塊裡(while、for)讀取這些final的成員變數的時候;
  2. 部分或全部的非迴圈程式碼塊裡讀取這些final的成員變數的時候;

為什麼要這樣做呢?

原因一、為了加快訪問速度;

將全域性變數賦值給方法的一個區域性變數,訪問的時候直接線上程棧裡面取,比訪問成員變數速度要快,讀取棧裡面的變數只需要一條指令,讀取成員變數則需要兩條指令;

原因二、為了安全;

如果只是為了訪問速度快,那麼直接使用一個普通的區域性變數即可,不需要加final,加了final原因就是為了多執行緒下的執行緒安全。

final的作用,一經初始化就無法被更改,並且保證物件訪問的記憶體重排序,保證物件的可見性,更詳細內容見這裡 

ps: 需要注意的是,當final變數為物件或者陣列時:
  1. 雖然我們不能講這個變數賦值為其他物件或者陣列,但是我們可以改變物件的域或者陣列中的元素。
  2. 執行緒對這個物件變數的域或者資料的元素的改變不具有執行緒可見性。

相關文章