Quantcast

Unsynchronized read guarantees

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Unsynchronized read guarantees

Bobrowski, Maciej

Hi,

 

Given a very simple class:

 

class Counter {

  private int val = 0;

 

  public int unsynchronizedGet() {

    return val;

  }

  public synchronized void increment() {

    val++;

  }

}

 

If I have one thread periodically calling increment() on an instance of Counter, and the other thread periodically reading the value (using unsynchronized get), my question is: are there any guarantees about what value the unsynchronizedGet returns? Can it be e.g. 0 for a first few reads, then e.g. 20 (because the new value was loaded from memory)? Or will it either always be 0 (cached in a register) or will it always keep on increasing (being read from memory)?

 

Any pointers would be greatly appreciated

 





NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unsynchronized read guarantees

Nathan & Ila Reynolds

Let’s take the following code.

 

while (unsynchronizedGet() == 0)

{

   // spin

}

 

JIT is allowed to inline unsynchronizedGet().  JIT is allowed to skip loading the field “val” and simply use it as a constant.  In fact, the entire loop could be optimized down to something like this.

 

Label:

   Goto Label;

 

As soon as you put a break point on the loop, the execute will switch back to bytecode and “val” will be loaded from memory.

 

To “fix” the code, you could declare “val” to be volatile.  This will force “val” to be loaded from cache/RAM every time.

 

-Nathan

 

From: Concurrency-interest [mailto:[hidden email]] On Behalf Of Bobrowski, Maciej
Sent: Tuesday, November 01, 2016 8:53 AM
To: [hidden email]
Subject: [concurrency-interest] Unsynchronized read guarantees

 

Hi,

 

Given a very simple class:

 

class Counter {

  private int val = 0;

 

  public int unsynchronizedGet() {

    return val;

  }

  public synchronized void increment() {

    val++;

  }

}

 

If I have one thread periodically calling increment() on an instance of Counter, and the other thread periodically reading the value (using unsynchronized get), my question is: are there any guarantees about what value the unsynchronizedGet returns? Can it be e.g. 0 for a first few reads, then e.g. 20 (because the new value was loaded from memory)? Or will it either always be 0 (cached in a register) or will it always keep on increasing (being read from memory)?

 

Any pointers would be greatly appreciated

 

 



NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unsynchronized read guarantees

Bobrowski, Maciej

So basically, I could put a breakpoint at any time, causing unpredictable behaviour for the value of counter, is that right?

 

From: Nathan & Ila Reynolds [mailto:[hidden email]]
Sent: 01 November 2016 15:41
To: Bobrowski, Maciej (IST); [hidden email]
Subject: RE: [concurrency-interest] Unsynchronized read guarantees

 

Let’s take the following code.

 

while (unsynchronizedGet() == 0)

{

   // spin

}

 

JIT is allowed to inline unsynchronizedGet().  JIT is allowed to skip loading the field “val” and simply use it as a constant.  In fact, the entire loop could be optimized down to something like this.

 

Label:

   Goto Label;

 

As soon as you put a break point on the loop, the execute will switch back to bytecode and “val” will be loaded from memory.

 

To “fix” the code, you could declare “val” to be volatile.  This will force “val” to be loaded from cache/RAM every time.

 

-Nathan

 

From: Concurrency-interest [[hidden email]] On Behalf Of Bobrowski, Maciej
Sent: Tuesday, November 01, 2016 8:53 AM
To: [hidden email]
Subject: [concurrency-interest] Unsynchronized read guarantees

 

Hi,

 

Given a very simple class:

 

class Counter {

  private int val = 0;

 

  public int unsynchronizedGet() {

    return val;

  }

  public synchronized void increment() {

    val++;

  }

}

 

If I have one thread periodically calling increment() on an instance of Counter, and the other thread periodically reading the value (using unsynchronized get), my question is: are there any guarantees about what value the unsynchronizedGet returns? Can it be e.g. 0 for a first few reads, then e.g. 20 (because the new value was loaded from memory)? Or will it either always be 0 (cached in a register) or will it always keep on increasing (being read from memory)?

 

Any pointers would be greatly appreciated

 

 



NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.





NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unsynchronized read guarantees

Henrik Johansson-8

We actually saw this break in some old code between updates of the jvm. Not sure exactly when but stuff broke spectacularly and fortunately making the one affected variable volatile fixed it. It was a little bit funny and a very enlightening teaching moment.


On Tue, Nov 1, 2016, 17:21 Bobrowski, Maciej <[hidden email]> wrote:

So basically, I could put a breakpoint at any time, causing unpredictable behaviour for the value of counter, is that right?

 

From: Nathan & Ila Reynolds [mailto:[hidden email]]
Sent: 01 November 2016 15:41
To: Bobrowski, Maciej (IST); [hidden email]
Subject: RE: [concurrency-interest] Unsynchronized read guarantees

 

Let’s take the following code.

 

while (unsynchronizedGet() == 0)

{

   // spin

}

 

JIT is allowed to inline unsynchronizedGet().  JIT is allowed to skip loading the field “val” and simply use it as a constant.  In fact, the entire loop could be optimized down to something like this.

 

Label:

   Goto Label;

 

As soon as you put a break point on the loop, the execute will switch back to bytecode and “val” will be loaded from memory.

 

To “fix” the code, you could declare “val” to be volatile.  This will force “val” to be loaded from cache/RAM every time.

 

-Nathan

 

From: Concurrency-interest [[hidden email]] On Behalf Of Bobrowski, Maciej
Sent: Tuesday, November 01, 2016 8:53 AM
To: [hidden email]
Subject: [concurrency-interest] Unsynchronized read guarantees

 

Hi,

 

Given a very simple class:

 

class Counter {

  private int val = 0;

 

  public int unsynchronizedGet() {

    return val;

  }

  public synchronized void increment() {

    val++;

  }

}

 

If I have one thread periodically calling increment() on an instance of Counter, and the other thread periodically reading the value (using unsynchronized get), my question is: are there any guarantees about what value the unsynchronizedGet returns? Can it be e.g. 0 for a first few reads, then e.g. 20 (because the new value was loaded from memory)? Or will it either always be 0 (cached in a register) or will it always keep on increasing (being read from memory)?

 

Any pointers would be greatly appreciated

 

 



NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.





NOTICE: Morgan Stanley is not acting as a municipal advisor and the opinions or views contained herein are not intended to be, and do not constitute, advice within the meaning of Section 975 of the Dodd-Frank Wall Street Reform and Consumer Protection Act. If you have received this communication in error, please destroy all electronic and paper copies and notify the sender immediately. Mistransmission is not intended to waive confidentiality or privilege. Morgan Stanley reserves the right, to the extent permitted under applicable law, to monitor electronic communications. This message is subject to terms available at the following link: http://www.morganstanley.com/disclaimers  If you cannot access these links, please notify us by reply message and we will send the contents to you. By communicating with Morgan Stanley you consent to the foregoing and to the voice recording of conversations with personnel of Morgan Stanley.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Unsynchronized read guarantees

Aleksey Shipilev-3
In reply to this post by Bobrowski, Maciej
On 11/01/2016 03:53 PM, Bobrowski, Maciej wrote:

> Given a very simple class:
>
> class Counter {
>   private int val = 0;
>   public int unsynchronizedGet() {
>     return val;
>   }
>
>   public synchronized void increment() {
>     val++;
>   }
> }
>
> If I have one thread periodically calling increment() on an instance of
> Counter, and the other thread periodically reading the value (using
> unsynchronized get), my question is: are there any guarantees about what
> value the unsynchronizedGet returns? Can it be e.g. 0 for a first few
> reads, then e.g. 20 (because the new value was loaded from memory)? Or
> will it either always be 0 (cached in a register) or will it always keep
> on increasing (being read from memory)?
This is the data race. With the naked example as above, JMM gives
(almost) no promises about the values you can read. Your explanation
hinges on the mental model of cache coherent memory, and once you hit
the hardware, most hardware would indeed work like you describe. But the
model itself is weaker, and if you do e.g.:

Counter cnt = ...;
int r1 = cnt.unsynchronizedGet();
int r2 = cnt.unsynchronizedGet();

...then model allows observing (r2 < r1).

Do not rely on data races!

More discussion:
https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/#wishful-hb-actual

Thanks,
-Aleksey


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (836 bytes) Download Attachment
Loading...