Yilong,

On 9/15/15 12:59 PM, Yilong Li wrote:
> On Tue, Sep 15, 2015 at 7:19 AM, Mark Thomas <ma...@apache.org> wrote:
> 
>> On 13/09/2015 21:59, Yilong Li wrote:
>>> Sorry about the vague explanation. But the actual reasons are not the
>> point
>>> here.
>>
>> No, that is exactly the point. When you claim that something that
>> appears to be working without issue for many, many users then you need
>> to provide a justification for why there is an issue to back up the
>> claims you are making.
>>
>>> The only thing matters is the Java memory model. And the article I
>>> refer to explain exactly why and how this can happen.
>>
>> No, it didn't. I read that article (and parts of the JMM). While the
>> article did state there was a problem it did not explain why there was a
>> problem.
>>
>> Long experience has lead us to be sceptical of bugs reported by
>> automated tools. When looking at such bugs and we can't see what the
>> problem is and the person raising the bug can't provide a clear
>> explanation - and continues not to provide a clear explanation when
>> asked for one several times - then that is the point where we start to
>> think the problem is with the tool.
>>
> 
> Sorry, I should not assume that the concepts such as happens-before order
> and memory model are well understood. Let's talk about how this is allowed
> to happen under JMM. Consider the this example again:
> 
> if (st_200 == null ) {
>     st_200 = sm.getString("sc.200");
> }
> return st_200;
> 
> The following is a valid execution trace consists of 5 events:
>             T1                       T2
> 1   READ  null
> 2   WRITE s
> 3                                 READ s
> 4                                 READ ???
> 5   READ  s
> 
> , where s is the result of sm.getString("sc.200").
> 
> T1 sees null in field st_200, initializes it, and return the initialized
> value, while T2 sees a non-null value in st_200 and skips the
> initialization. The question is what value T2 can read and then return in
> event 4. This is addressed in JLS $17.4.5 Happens-before Order (
> https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5):

I think you are mistaking the above code with something more like this:

private String s;

public String getString()
{
  if(null == s)
    s = new String("foo");

   return s;
}

In the above case, the reference "s" may for a short time be a reference
to an uninitialized object of type String. This can be problematic.
Imagine the psusdo-bytecode below generated by the compiler:

1:   push s
3:   ifnull goto 8
5:   goto X
8:   new java.lang.String
10:  dup
11:  store s
13:  push "foo"
15:  call java.lang.String.<init>

If T1 executes the instruction on line 11 and then T2 sees that
reference before T1 gets a change to call the String constructor, it's a
mess.

But, since the initialization of the String coming from
StringManager.getString is fully-constructed before any assignment can
take place, this is completely safe.

As Mark said, reference assignment is guaranteed to be atomic, so T1
while and T2 can disagree about the value of s, it will never be true
that either thread sees s as non-null but also not yet initialized.

In this particular case, the race condition does in fact exist, but
nobody cares: if s gets initialized more than once (to the same value,
in fact), it's no harm to the running program. Even if the values were
different (e.g. ResourceBundle hands-out String values that aren't
consistent), it wouldn't matter to client code.

I'm having trouble understanding Chuck's parallel response to this. :/

-chris

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to