2
public E poll() {
    final AtomicInteger count = this.count;
    if (count.get() == 0)
        return null;
    E x = null;
    int c = -1;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        if (count.get() > 0) {
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        }
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

this.count をローカル変数に割り当てる理由と、ローカル変数が final として宣言された理由を説明できる人はいますか?

4

3 に答える 3

2

this.count をローカル変数に割り当てる理由を誰か説明できますか

ローカル変数へのアクセスはインスタンス変数へのアクセスよりもわずかに安価であるため、パフォーマンスが向上する可能性があります。この投稿はこれをサポートしているようです。ただし、必要ではないかもしれない極端な最適化であるとも言っています。

また、なぜローカル変数が final として宣言されたのですか?

フィールドもソースコードのようにcount定義されているようです。ローカル変数を として宣言することで、一貫性を保ちたいだけかもしれません。finalfinal

于 2013-10-23T20:42:10.283 に答える
0

次のようなことをすることで私が見ることができる唯一の価値:

final AtomicInteger count = this.count;

と:

final ReentrantLock takeLock = this.takeLock;

is: 元のメンバーが final として宣言されておらず、作成者が将来このコードを維持するプログラマーに通知したい場合 - これらのオブジェクトへの参照を変更しないように (final宣言によって達成されます) )。

更新:
このコードは、Doug Lea によって書かれたLinkedBlockingQueueの実装から取られています。assylias が上に投稿したリンクによると、Marko は次のように書いています。

また、問題のメンバー変数が volatile ではなく final である場合でも、スタックの場所からの読み取りはランダムなヒープの場所からの読み取りよりもキャッシュに適しているため、このイディオムは CPU キャッシュに関係しています。ローカル変数が CPU レジスタにバインドされる可能性も高くなります。

この後者のケースについては、実際にはいくつかの論争があります。JIT コンパイラーは通常、これらの懸念事項を処理しますが、Doug Lea は、一般原則に固執する人の 1 人です。

于 2013-10-23T18:27:45.520 に答える