Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the volatile field copied to a local variable when doing double check locking

I am reading about double check locking from Effective Java. The code does the following:

private volatile FieldType field;  
FieldType getField() {  
    FieldType result = field;  
    if (result == null) { // First check (no locking)  
        synchronized(this) {   
        result = field;  
        if (result == null) // Second check (with locking)  
            field = result = computeFieldValue();  
        }  
    }  
    return result;  
}    

It says that using result seems unneeded but actually ensures that the field is only read only once in the common case where it is already initialized.

But I don't understand this. What is the difference with doing if(field == null) directly? I don't understand why if (result == null) is different, let alone better as stated.

like image 403
Jim Avatar asked May 09 '12 08:05

Jim


1 Answers

The explanation is on the next page (emphasis by me):

What this variable does is to ensure that field is read only once in the common case where it’s already initialized. While not strictly necessary, this may improve performance and is more elegant by the standards applied to low-level concurrent programming. On my machine, the method above is about 25 percent faster than the obvious version without a local variable.

For reference, the quote is from p. 284 of Item 71: Use lazy initialization judiciously in Effective Java 2nd Edition.

Update: the difference between reading a local vs a volatile variable is that the former may be optimized better. Volatile variables can't be stored in registers or caches, nor memory operations on them reordered. Moreover, reading a volatile variable may trigger memory synchronization between different threads.

See Java Concurrency in Practice, section 3.1.4: Volatile Variables for more details.

like image 91
Péter Török Avatar answered Jan 14 '23 21:01

Péter Török