Is this a better version of Double Check Locking without volatile and synchronization overhead

Deadly 提交于 2019-12-01 03:30:53

问题


Below code snippet is from Effective Java 2nd Edition Double Checked Locking

// Double-check idiom for lazy initialization of instance fields

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

From what i know the main Problem with Double Checked Locking is the reordering inside second check locking so that the other thread might see the values of field/result as set which may be infact still be in executing. To avoid this we make the reference of field as volatile to gurantee visibility and reordering.

But this can be achieved by the below code also

private FieldType field; // non volatile
private volatile boolean fence = false;

FieldType getField() {
    if (field == null) {  // First check (no locking) // no volatile read
        synchronized(this) {   //  inside synch block no problem of visibilty will latest           //value  of field 
            if (field == null) {// Second check (with locking)  
                Object obj =  computeFieldValue();
             fence = true; // any volatile write will take. this will make sure statements are //not reorder with setting field as non null.
            field = (FieldType)obj; // this will be only set after computeFieldValue has been //completed fully
           }
        }
    }
    return field;
}

So after when the initialization have been done, then no thread will have to for volatile read or synchronization overhead. Please see if my assumptions are right or not?


回答1:


There is no way to achieve "cheap" double-checked locking in pure JMM; something got to give.

Your solution doesn't work because a volatile write can be reordered with a following normal action. See jsr133 cookbook for allowed reordering in the so called "roach motel" model. "Roach motel" is a stronger model than JMM, so if your solution fails in roach motel, it fails in JMM.

roach motel model
reordering between a normal action and a volatile/monitor action

   --                              <--
  |                                   |
  |    VolatileLoad / MonitorEnter    | forbidden
  |                                   |
   --> allowed                      --


   --> allowed                      --
  |                                   | 
  |    VolatileStore / MonitorExit    | forbidden
  |                                   |
   --                              <--

There is a way to deter reordering of two normal actions in "roach motel" model

(1) action#1
(2) volatile write
(3) volatile read
(4) action#4

(1) cannot be reordered with (2), and (4) cannot be reordered with (3), therefore (1) and (4) cannot be reordered.

However, be warned that "roach motel" model is a stronger model than JMM. You cannot be sure that a JVM conforms to roach motel model. For a concrete example

action#1
synchronized(new Object()){}
synchronized(new Object()){}
action#4

according to roach motel, action#1 and action#4 can't be reordered; however JVM can legitimately (allowed by JMM) remove the two sync block then reorder the remaining two actions.




回答2:


The JLS (Section 17.4.5) states:

"A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field."

You are not reading the fence variable after it is updated, so there is no "happens-before" relationship between the thread that updates fence and any second thread. That means that the second thread is not guaranteed to see the updates to the field variable made by the first thread.

In short, your "improved" code is a broken implementation of double-checked locking.




回答3:


According to sources I trust, it seems to be a working and safe code. Write of a volatile variable must enforce the write of all other variables and can be reordered neither with volatile nor with normal assignments.



来源:https://stackoverflow.com/questions/17169145/is-this-a-better-version-of-double-check-locking-without-volatile-and-synchroniz

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!