82

では、ロックを必要とするすべてのメソッドは、を呼び出す前ArrayBlockingQueueにロックをローカル変数にコピーします。finallock()

public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            insert(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

フィールドがのときにthis.lockローカル変数にコピーする理由はありますか?lockthis.lockfinal

E[]さらに、操作する前にのローカル コピーも使用します。

private E extract() {
    final E[] items = this.items;
    E x = items[takeIndex];
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal();
    return x;
}

final フィールドをローカルの final 変数にコピーする理由はありますか?

4

2 に答える 2

69

これは、クラスの作成者である Doug Lea が好んで使用する極端な最適化です。これは、core-libs-dev メーリング リストの最近のスレッドに投稿された、この正確な主題に関する投稿で、あなたの質問にかなりよく答えています。

投稿から:

...ローカルにコピーすると、最小のバイトコードが生成されます。低レベルのコードでは、マシンに少し近いコードを書くとよいでしょう。

于 2010-05-07T03:29:47.690 に答える
13

このスレッドはいくつかの答えを提供します。実質的に:

  • コンパイラーは、メソッド内で final フィールドが変更されないことを簡単に証明できません (リフレクション/シリアライゼーションなどにより)。
  • 現在のほとんどのコンパイラは実際には試行しないため、使用するたびに最終フィールドをリロードする必要があり、キャッシュ ミスやページ フォールトが発生する可能性があります。
  • ローカル変数に格納すると、JVM は 1 つのロードのみを実行するように強制されます
于 2013-03-14T11:09:22.727 に答える