Reading Integers from Threads

  • Thread starter Thread starter Fred West
  • Start date Start date
F

Fred West

I have a class with a private Int32 data member that gets modified from
multiple background threads. To synchronize these modifications I use the
lock statement:

Int32 count = 0;
object countLock = new object();

....
lock (countLock) count++;

....
lock(countLock) count = newValue;


My question is that when I wish to read this value (from yet another thread)
do I need to wrap it in a lock statement. For example, the class has the
following property:

public Int32 Count{get{return count;}}

The reading of the value is done extensively and I do not wish to have the
overhead of the lock statement. Can a thread lose it's turn in the middle of
a lock statement? If so, is it possible that the Int32 field is only
partially updated with it's new value and when I go to read it? What if my
field was an Int64?

Thanks,

- Fred
 
When working with Int32, instead of using locks, you can use the
Increment, Decrement and Exchange methods on the Interlocked class. On
a 32bit system, they are guarantteed to be atomic, not only with each
other, but with other operations as well. you don't need a lock to
read.

same is not true for Int64 on a 32bit system, however. Reading without
a lock could result in partially updated data.
 
In addition to what Daniel said, you can easily encapsulate this in a
method and property in the class like this:

public int Count
{
get
{
// Lock.
lock (countLock)
{
// Return the value.
return countLock;
}
}
}

public int IncrementCount()
{
// Call the overload, passing 1.
return IncrementCount(1);
}

public int IncrementCount(int amount)
{
// Lock.
lock (countLock)
{
// Increment the count.
count += amount;

// Return the new value.
return count;
}
}

Then, you can use these methods everywhere, and not have to worry about
handling the lock in each situation. Ahh, the joys of code encapsulation.
=)

Also, if you were doing just assignment or a read, you could declare the
variable as volatile, but that would limit the "thread-safeness" of your
operation to just that assignment or read (and it doesn't work on 64-bit
values).

And no, a thread can not lose it's value in the middle of a lock
statement. If you try and access a variable where all access is blocked by
lock statements, those statements will wait until they can acquire the lock
in that thread.

Hope this helps.
 
Fred West said:
I have a class with a private Int32 data member that gets modified from
multiple background threads. To synchronize these modifications I use the
lock statement:

Int32 count = 0;
object countLock = new object();

...
lock (countLock) count++;

...
lock(countLock) count = newValue;


My question is that when I wish to read this value (from yet another
thread) do I need to wrap it in a lock statement. For example, the class
has the following property:

public Int32 Count{get{return count;}}

The reading of the value is done extensively and I do not wish to have the
overhead of the lock statement. Can a thread lose it's turn in the middle
of a lock statement? If so, is it possible that the Int32 field is only
partially updated with it's new value and when I go to read it? What if my
field was an Int64?

Thanks,

- Fred

Int32 reads are atomic operations, so the value you get cannot be partially
updated, however without synchronizing the access, you aren't guaranteed to
read the last value written on multi CPU boxes.
If all you need to protect is a simple integer value, you might consider to
use Interlocked methods instead of using such fine grained locks to perform
atomic, thread-safe operations on Int32 values, they are faster than taking
locks and have less overhead when contention rate is high. However, you
should not use them on longer values (Int64, Doubles), for such values I
would suggest you to use locks which are extremely fast in non-contention
cases.

Willy.
 
Back
Top