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;
}

Can anyone explain why we assign this.count to a local variable, and also why the local variable declared as final?

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125
  • @assylias the `volatile` explanation makes (some) sense in regards to `AtomicInteger` - not in regards to a `ReentrantLock`. – Nir Alfasi Oct 23 '13 at 18:41
  • @assylias further, in regards to `AtomicInteger`: if that was the case the writer could simply use `count.get()` in the beginning of the method and work with `int`. – Nir Alfasi Oct 23 '13 at 18:47
  • @assylias which leaves only the explanation that if the variable is declared `final` there's a "higher chance that the local var will end up bound to a CPU register" – Nir Alfasi Oct 23 '13 at 18:58
  • @alfasin yes that's what it is. Although there is another parameter: optimising final fields is not that straightforward for a compiler - in particular, because of reflection, a final field might change. A local variable can't. The result being that some compiler optimisations are available for local variables that are not for final fields. – assylias Oct 23 '13 at 21:38

3 Answers3

2

Can anyone explain why we assign this.count to a local variable

It might potentially improve the performance since accessing a local variable is slightly cheaper than accessing an instance variable. This post seems to support this. However, they also say that it is an extreme optimization which might not be necessary.

and also why the local variable declared as final?

It seems that the field count is defined as final in the source code as well. They might just want to be consistent by declaring the local variable as final.

Terry Li
  • 16,870
  • 30
  • 89
  • 134
0

The only value I can see in doing things like:

final AtomicInteger count = this.count;

and:

final ReentrantLock takeLock = this.takeLock;

is: in case the original member was not declared as final, and the writer wanted to signal the programmers that will maintain this code in the future - to not, by any means, change the reference to these objects (which is achieved by the final declaration).

UPDATE:
This code is taken from the implementation of LinkedBlockingQueue written by Doug Lea. According to the link that assylias posted above, Marko wrote:

Also, even when the member variable in question is not volatile but final, this idiom has to do with CPU caches as reading from a stack location is more cache-friendly than reading from a random heap location. There is also a higher chance that the local var will end up bound to a CPU register.

For this latter case there is actually some controversy, since the JIT compiler will usually take care of those concerns, but Doug Lea is one of the guys who sticks with it on general principle.

Community
  • 1
  • 1
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • I think this snippet is taken from the jdk itself and the inexperienced writer is the main contributor to the concurrent api... I would not bet on him not knowing what he is doing... – assylias Oct 23 '13 at 18:34
  • @Giodude http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/LinkedBlockingQueue.java#LinkedBlockingQueue.poll%28%29 – assylias Oct 23 '13 at 21:35
0

I'm sure it has to do with various compiler optimizations. In general, compiler hints like this aren't necessary, as the compiler in theory should be able to figure this particular optimization out itself, but the JDK writers probably have better knowledge about the actual practical implementation of the compiler, and therefore know that this will create faster bytecode.

LadyCailin
  • 849
  • 10
  • 26