Home All Groups Group Topic Archive Search About

ReaderWriterLock with Interlocked?

Author
13 Jan 2007 8:57 PM
Amir The Ruler
Found this piece of code in .Net SDK 2.0. Why do we need to use Interlocked
although AcquireWriterLock is supposed to serialize access and do the traick?

// C#
ReaderWriterLock rwLock = new ReaderWriterLock();
int counter = 0;

try
{
    rwLock.AcquireWriterLock(1000);

    try
    {
        Interlocked.Increment(ref counter);
    }
    finally
    {
        rwLock.ReleaseWriterLock();
    }
}
catch (ApplicationException)
{
    Console.WriteLine("Failed to get a Writer Lock");
}

Thank you for any tips.

Author
13 Jan 2007 10:08 PM
Barry Kelly
Amir The Ruler wrote:

Show quote
> Found this piece of code in .Net SDK 2.0. Why do we need to use Interlocked
> although AcquireWriterLock is supposed to serialize access and do the traick?
>
> // C#
> ReaderWriterLock rwLock = new ReaderWriterLock();
> int counter = 0;
>
> try
> {
>     rwLock.AcquireWriterLock(1000);
>
>     try
>     {
>         Interlocked.Increment(ref counter);
>     }
>     finally
>     {
>         rwLock.ReleaseWriterLock();
>     }
> }
> catch (ApplicationException)
> {
>     Console.WriteLine("Failed to get a Writer Lock");
> }
>
> Thank you for any tips.

That depends on whether 'counter' is used without synchronization
elsewhere in the body of code. If it isn't, then the locking is
redundant. (FWIW, it wouldn't be the first crappy piece of code in the
samples with the SDK & docs.)

-- Barry

Author
14 Jan 2007 12:55 AM
Michael Nemtsev
Hello Barry,

int (counter in our case) is atomic, afailk (if alignment wasn't changed).

Shouldn't this to be a reason to avoid Increment at all?!


---
WBR,
Michael  Nemtsev [C# MVP] :: blog: http://spaces.live.com/laflour

"The greatest danger for most of us is not that our aim is too high and we
miss it, but that it is too low and we reach it" (c) Michelangelo

BK> Amir The Ruler wrote:
BK>
Show quote
>> Found this piece of code in .Net SDK 2.0. Why do we need to use
>> Interlocked although AcquireWriterLock is supposed to serialize
>> access and do the traick?
>>
>> // C#
>> ReaderWriterLock rwLock = new ReaderWriterLock();
>> int counter = 0;
>> try
>> {
>> rwLock.AcquireWriterLock(1000);
>> try
>> {
>> Interlocked.Increment(ref counter);
>> }

BK> That depends on whether 'counter' is used without synchronization
BK> elsewhere in the body of code. If it isn't, then the locking is
BK> redundant. (FWIW, it wouldn't be the first crappy piece of code in
BK> the samples with the SDK & docs.)
Author
14 Jan 2007 1:46 PM
Barry Kelly
Michael Nemtsev wrote:

> int (counter in our case) is atomic, afailk (if alignment wasn't changed).
>
> Shouldn't this to be a reason to avoid Increment at all?!

Loads and assignments individually are atomic, but increment requires an
atomic combination of "load and increment and assignment" all in the one
"transaction". Thus either you need manual synchronization or
Interlocked.Increment etc.

Incrementing an int32 with a memory operand (e.g. 'inc dword ptr [eax]')
on a single-CPU x86 system, with no dual core and no hyperthreading, is
atomic. Other architectures, more CPUs, etc., almost certainly require
some kind of mutual exclusion or interlocked operation to work.

-- Barry

Author
14 Jan 2007 2:04 PM
Henning Krause [MVP - Exchange]
Hello,

> Loads and assignments individually are atomic, but increment requires an
> atomic combination of "load and increment and assignment" all in the one
> "transaction". Thus either you need manual synchronization or
> Interlocked.Increment etc.

However, reading a 64bit value on a 32bit architecture is not atomic and
must be protected as well...

Best regards,
Henning Krause
Author
14 Jan 2007 5:10 PM
Barry Kelly
Henning Krause [MVP - Exchange] wrote:

> Hello,
>
> > Loads and assignments individually are atomic, but increment requires an
> > atomic combination of "load and increment and assignment" all in the one
> > "transaction". Thus either you need manual synchronization or
> > Interlocked.Increment etc.
>
> However, reading a 64bit value on a 32bit architecture is not atomic and
> must be protected as well...

Of course, we're talking about an int here.

-- Barry

Author
14 Jan 2007 7:54 PM
Jon Skeet [C# MVP]
Michael Nemtsev <nemt***@msn.com> wrote:
> int (counter in our case) is atomic, afailk (if alignment wasn't changed).
>
> Shouldn't this to be a reason to avoid Increment at all?!

No. Just because each operation (fetch/store) is atomic doesn't mean
that an increment (fetch/increment/store) is atomic:

counter=0

Thread 1                      Thread 2
Fetch counter(0)             
                              Fetch counter(0)
Increment (1)
Store (1)
                              Increment (1)
                              Store (1)

The result of two increments should be 2, but it's only 1.

Furthermore, atomic doesn't imply volatile - a fetch could see an old
value. See
http://www.pobox.com/~skeet/csharp/threads/volatility.shtml for more
information.

--
Jon Skeet - <sk***@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
Author
14 Jan 2007 2:24 AM
Amir The Ruler
actually that code is copied from MCTS Self-Paced Training Kit (Exam 70-536)
but i verified and found almost the same thing in sdk:

rwl.AcquireWriterLock(timeOut);
            try
            {
                // It is safe for this thread to read or write
                // from the shared resource.
                resource = rnd.Next(500);
                Display("writes resource value " + resource);
                Interlocked.Increment(ref writes);

it yet doesn't make sense to use 2 sync mechanisms at once . and those
variables are not used anywhere else without synchronization.


Show quote
"Barry Kelly" wrote:

> Amir The Ruler wrote:
>
> > Found this piece of code in .Net SDK 2.0. Why do we need to use Interlocked
> > although AcquireWriterLock is supposed to serialize access and do the traick?
> >
> > // C#
> > ReaderWriterLock rwLock = new ReaderWriterLock();
> > int counter = 0;
> >
> > try
> > {
> >     rwLock.AcquireWriterLock(1000);
> >
> >     try
> >     {
> >         Interlocked.Increment(ref counter);
> >     }
> >     finally
> >     {
> >         rwLock.ReleaseWriterLock();
> >     }
> > }
> > catch (ApplicationException)
> > {
> >     Console.WriteLine("Failed to get a Writer Lock");
> > }
> >
> > Thank you for any tips.
>
> That depends on whether 'counter' is used without synchronization
> elsewhere in the body of code. If it isn't, then the locking is
> redundant. (FWIW, it wouldn't be the first crappy piece of code in the
> samples with the SDK & docs.)
>
> -- Barry
>
> --
> http://barrkel.blogspot.com/
>

AddThis Social Bookmark Button