The Interlocked on the Edge of Forever

This is a discussion on The Interlocked on the Edge of Forever within the Framework and Interface Programming forums in category; | To make changes to this is easy enough: | InterlockedExchange(ref _firstTime, 1); | | ... or I can use the InterlockedCompareExchange: | int oldValue = InterlockedCompareExchange(ref _firstTime, 1, 0); | | No problems here. | | ... but, if I just want to read the value, I CANNOT do: | | int myValue = _firstTime; | or | if (_fistTime==0) | | Doing these requires a memory barrier of some type (volatile variable, | monitor, etc) to have any degree of reliability. you can. The Interlocked write ensures this across all cpus and cache. Any thread reading the var ...

Go Back   Application Development Forum > Framework and Interface Programming

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #11  
Old 05-06-2007, 01:38 AM
William Stacey [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

| To make changes to this is easy enough:
| InterlockedExchange(ref _firstTime, 1);
|
| ... or I can use the InterlockedCompareExchange:
| int oldValue = InterlockedCompareExchange(ref _firstTime, 1, 0);
|
| No problems here.
|
| ... but, if I just want to read the value, I CANNOT do:
|
| int myValue = _firstTime;
| or
| if (_fistTime==0)
|
| Doing these requires a memory barrier of some type (volatile variable,
| monitor, etc) to have any degree of reliability.

you can. The Interlocked write ensures this across all cpus and cache. Any
thread reading the var after the Interlocked write will see the correct var
so it is a memory barrier without a volatile modifier. All locks are
ultimatley built on interlocked at the lowest level to get this behavior.
So for reads, you can just go "if (var == 2){}". Naturally, this works for
a single var. If you have multiple invariants you need to protect, you
probabaly need a lock.


Reply With Quote
  #12  
Old 05-06-2007, 02:49 AM
Jon Skeet [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

William Stacey [C# MVP] <william.stacey> wrote:
> | Doing these requires a memory barrier of some type (volatile variable,
> | monitor, etc) to have any degree of reliability.
>
> you can. The Interlocked write ensures this across all cpus and cache. Any
> thread reading the var after the Interlocked write will see the correct var
> so it is a memory barrier without a volatile modifier.


But surely that's only guaranteed if the read *actually* happens after
the Interlocked write occurs. If the variable isn't volatile, there's
nothing to stop the reading thread from having reordered the reads. For
instance:

int x=0, y=0;

....

Thread 1:
Interlocked.Increment (ref x, 1);
Interlocked.Increment (ref y, 1);



Thread 2:
int a = x;
int b = y;

The JIT *could* reorder the reads of x and y in thread 2, such that you
get a=0, b=1, despite the fact that x is incremented before y. That
wouldn't be the case with volatile variables.


At least, that's how I understand it.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Reply With Quote
  #13  
Old 05-06-2007, 02:49 AM
Jon Skeet [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

William Stacey [C# MVP] <william.stacey> wrote:
> | Doing these requires a memory barrier of some type (volatile variable,
> | monitor, etc) to have any degree of reliability.
>
> you can. The Interlocked write ensures this across all cpus and cache. Any
> thread reading the var after the Interlocked write will see the correct var
> so it is a memory barrier without a volatile modifier.


But surely that's only guaranteed if the read *actually* happens after
the Interlocked write occurs. If the variable isn't volatile, there's
nothing to stop the reading thread from having reordered the reads. For
instance:

int x=0, y=0;

....

Thread 1:
Interlocked.Increment (ref x, 1);
Interlocked.Increment (ref y, 1);



Thread 2:
int a = x;
int b = y;

The JIT *could* reorder the reads of x and y in thread 2, such that you
get a=0, b=1, despite the fact that x is incremented before y. That
wouldn't be the case with volatile variables.


At least, that's how I understand it.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Reply With Quote
  #14  
Old 05-06-2007, 03:28 PM
William Stacey [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

| But surely that's only guaranteed if the read *actually* happens after
| the Interlocked write occurs. If the variable isn't volatile, there's
| nothing to stop the reading thread from having reordered the reads. For
| instance:

Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
reader will never see x==0 (until it wraps). So a read on x or y is volatile
using an interlocked. Naturally, in either method, a reader could read x and
y after x was incremented, but before y was incremented because there is no
lock here. But this is a different problem (i.e race). If we need both vars
to be atomic in respect to each other and handled as an invariant "set",
then we need a lock of some type protecting the set. As I said, maybe I am
not following your intent and will slap my head.
--wjs


Reply With Quote
  #15  
Old 05-06-2007, 03:28 PM
William Stacey [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

| But surely that's only guaranteed if the read *actually* happens after
| the Interlocked write occurs. If the variable isn't volatile, there's
| nothing to stop the reading thread from having reordered the reads. For
| instance:

Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
reader will never see x==0 (until it wraps). So a read on x or y is volatile
using an interlocked. Naturally, in either method, a reader could read x and
y after x was incremented, but before y was incremented because there is no
lock here. But this is a different problem (i.e race). If we need both vars
to be atomic in respect to each other and handled as an invariant "set",
then we need a lock of some type protecting the set. As I said, maybe I am
not following your intent and will slap my head.
--wjs


Reply With Quote
  #16  
Old 05-06-2007, 06:46 PM
Jon Skeet [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

William Stacey [C# MVP] <william.stacey> wrote:
> | But surely that's only guaranteed if the read *actually* happens after
> | the Interlocked write occurs. If the variable isn't volatile, there's
> | nothing to stop the reading thread from having reordered the reads. For
> | instance:
>
> Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
> reader will never see x==0 (until it wraps). So a read on x or y is volatile
> using an interlocked. Naturally, in either method, a reader could read x and
> y after x was incremented, but before y was incremented because there is no
> lock here.


I still believe that it can read y before either of them are
incremented, and x after both of them are incremented. There's nothing
to stop the JIT from reordering the reads to read y before x, because
they're not volatile. I wouldn't be surprised to learn that the
interlocked operation makes sure that when it *does* try to read x and
y, those values are really the latest ones, but I don't think there's
any guarantee about the order of those reads unless at least one of
them is volatile. (It's nearly midnight, so I can't be bothered to work
out which it should be - y, I think.)

I definitely *wasn't* talking about the atomicity of the two operations
- just the ordering.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Reply With Quote
  #17  
Old 05-06-2007, 06:46 PM
Jon Skeet [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

William Stacey [C# MVP] <william.stacey> wrote:
> | But surely that's only guaranteed if the read *actually* happens after
> | the Interlocked write occurs. If the variable isn't volatile, there's
> | nothing to stop the reading thread from having reordered the reads. For
> | instance:
>
> Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
> reader will never see x==0 (until it wraps). So a read on x or y is volatile
> using an interlocked. Naturally, in either method, a reader could read x and
> y after x was incremented, but before y was incremented because there is no
> lock here.


I still believe that it can read y before either of them are
incremented, and x after both of them are incremented. There's nothing
to stop the JIT from reordering the reads to read y before x, because
they're not volatile. I wouldn't be surprised to learn that the
interlocked operation makes sure that when it *does* try to read x and
y, those values are really the latest ones, but I don't think there's
any guarantee about the order of those reads unless at least one of
them is volatile. (It's nearly midnight, so I can't be bothered to work
out which it should be - y, I think.)

I definitely *wasn't* talking about the atomicity of the two operations
- just the ordering.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Reply With Quote
  #18  
Old 05-06-2007, 07:07 PM
William Stacey [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

So are you saying the JIT can reorder these two lines:
int a = x;
int b = y;

Like so:
int b = y;
int a = x;

? tia

--
William Stacey [C# MVP]



"Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message
news:MPG.20a86b07bb54e61e7d@msnews.microsoft.com.. .
| William Stacey [C# MVP] <william.stacey> wrote:
| > | But surely that's only guaranteed if the read *actually* happens after
| > | the Interlocked write occurs. If the variable isn't volatile, there's
| > | nothing to stop the reading thread from having reordered the reads.
For
| > | instance:
| >
| > Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
| > reader will never see x==0 (until it wraps). So a read on x or y is
volatile
| > using an interlocked. Naturally, in either method, a reader could read x
and
| > y after x was incremented, but before y was incremented because there is
no
| > lock here.
|
| I still believe that it can read y before either of them are
| incremented, and x after both of them are incremented. There's nothing
| to stop the JIT from reordering the reads to read y before x, because
| they're not volatile. I wouldn't be surprised to learn that the
| interlocked operation makes sure that when it *does* try to read x and
| y, those values are really the latest ones, but I don't think there's
| any guarantee about the order of those reads unless at least one of
| them is volatile. (It's nearly midnight, so I can't be bothered to work
| out which it should be - y, I think.)
|
| I definitely *wasn't* talking about the atomicity of the two operations
| - just the ordering.
|
| --
| Jon Skeet - <skeet@pobox.com>
| http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
| If replying to the group, please do not mail me too


Reply With Quote
  #19  
Old 05-06-2007, 07:07 PM
William Stacey [C# MVP]
Guest
 
Default Re: The Interlocked on the Edge of Forever

So are you saying the JIT can reorder these two lines:
int a = x;
int b = y;

Like so:
int b = y;
int a = x;

? tia

--
William Stacey [C# MVP]



"Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message
news:MPG.20a86b07bb54e61e7d@msnews.microsoft.com.. .
| William Stacey [C# MVP] <william.stacey> wrote:
| > | But surely that's only guaranteed if the read *actually* happens after
| > | the Interlocked write occurs. If the variable isn't volatile, there's
| > | nothing to stop the reading thread from having reordered the reads.
For
| > | instance:
| >
| > Hi Jon. Not sure I totally follow you here. If Interlocked x happens, a
| > reader will never see x==0 (until it wraps). So a read on x or y is
volatile
| > using an interlocked. Naturally, in either method, a reader could read x
and
| > y after x was incremented, but before y was incremented because there is
no
| > lock here.
|
| I still believe that it can read y before either of them are
| incremented, and x after both of them are incremented. There's nothing
| to stop the JIT from reordering the reads to read y before x, because
| they're not volatile. I wouldn't be surprised to learn that the
| interlocked operation makes sure that when it *does* try to read x and
| y, those values are really the latest ones, but I don't think there's
| any guarantee about the order of those reads unless at least one of
| them is volatile. (It's nearly midnight, so I can't be bothered to work
| out which it should be - y, I think.)
|
| I definitely *wasn't* talking about the atomicity of the two operations
| - just the ordering.
|
| --
| Jon Skeet - <skeet@pobox.com>
| http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
| If replying to the group, please do not mail me too


Reply With Quote
  #20  
Old 05-07-2007, 01:52 AM
Barry Kelly
Guest
 
Default Re: The Interlocked on the Edge of Forever

William Stacey [C# MVP] wrote:

> So are you saying the JIT can reorder these two lines:
> int a = x;
> int b = y;
>
> Like so:
> int b = y;
> int a = x;


Yes, if x and y are not volatile locations. The language of the spec is
that reads and writes to volatile locations are the only observable side
effects of memory access; memory accesses may be arbitrarily reordered
if they aren't volatile. For example, if the value of y has been loaded
to a register because it was used somewhere before the line 'int a =
x;', then the value of y used in the line 'int b = y;' may predate the
actual in-memory value of x, because the value may be used from the
register, rather than freshly loading it from memory. So, volatile can
inhibit these kinds of optimizations (avoiding redundant loads).

There's more to it than that, volatile reads have acquire semantics,
volatile writes release semantics. That has stronger guarantees than
just inhibiting optimization, as it affects e.g. write buffer reordering
in some processors.

-- Barry

--
http://barrkel.blogspot.com/
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 02:39 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.