1. 程式人生 > >類中欄位賦值給區域性變數後再使用意義何在?

類中欄位賦值給區域性變數後再使用意義何在?

Concurrency-interest郵件列表中有人問了這麼一個問題:ArrayBlockingQueue中有個物件欄位lock,在ArrayBlockingQueue的很多方法中,使用這個lock時都將其先賦值給一個區域性變數,然後再通過區域性變數呼叫lock上的方法,而沒有直接使用lock欄位,如remainingCapacity方法中先將this.lock賦值給一個區域性變數lock,然後再使用這個區域性變數:

public class ArrayBlockingQueue {
	private final ReentrantLock lock;
	
	//...other fields and methods
	
	public int remainingCapacity() {
		final ReentrantLock lock = this.lock;
		lock.lock();
		try {
			return items.length - count;
		} finally {
			lock.unlock();
		}
	}
}

而不是像這樣直接使用類中的欄位:

public class ArrayBlockingQueue {
	private final ReentrantLock lock;
	
	//...other fields and methods
	
	public int remainingCapacity() {
		this.lock.lock();
		try {
			return items.length - count;
		} finally {
			this.lock.unlock();
		}
	}
}

那麼為什麼要這麼做,有什麼理由或說法?

Doug Lea

給出了回覆,大意如下:

歸根究底是由於記憶體模型與OOP之間的原則不一致。

幾乎j.u.c包中的每個方法都採用了這樣一種策略:當一個值會被多次使用時,就將這個欄位讀出來賦值給區域性變數。雖然這種做法不雅觀,但檢查起來會更直觀。

final欄位也會做這樣處理,可能有些令人不解。這是因為JVM並不足夠智慧,不能充分利用JMM已經提供了安全保證的可優化點,比如可以不用重新載入final值到快取。相比過去,JVM在這方面有很大進步,但仍不夠智慧。

原文如下:

It’s ultimately due to the fundamental mismatch between memory models
and OOP