Question

I want to increment an unsigned integer from multiple threads.

I know about Interlocked.Increment, but it does not handle unsigned integers. I could use lock(), but I would rather not if possible for performance reasons.

Is it thread safe just to increment it in the normal way? It would not matter if the occasional increment got lost, as it's only used for statistics. What I don't want is the value to get corrupted.

Was it helpful?

Solution

You say you don't want to use lock for performance reasons - but have you tested it? An uncontested lock (which this is likely to be, by the sounds of it) is pretty cheap.

I generally go for "obviously correct" rather than "clever and possibly better performing" when it comes to threading (and in general, but especially for threading).

Benchmark your app with and without locking, and see whether you can even notice the difference. If locking makes a significant difference then sure, use cunning stuff. Otherwise, I'd just stick with a lock.

One thing you might want to do is use Interlocked.Increment with an int and just cast it when necessary to get a uint, like this:

using System;
using System.Reflection;
using System.Threading;

public class Test
{
    private static int count = int.MaxValue-1;

    public static uint IncrementCount()
    {
        int newValue = Interlocked.Increment(ref count);
        return unchecked((uint) newValue);
    }

    public static void Main()
    {
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
    }

}

Output:

2147483647
2147483648
2147483649

(In other words it wraps with no problems.)

OTHER TIPS

If you really need the full range of an unsigned int (2^32 - 1) rather than a signed int (2^31 -1), you could cast to an int64 (there is an Interlocked.Increment overload that takes int64) and then cast back to an unsigned int.

On systems using a twos complement representation of signed integers ("virtually all", according to wikipedia) incrementing an unsigned integer has the same effect as incrementing a signed integer represented using the same set of bits. Thus, one can use InterlockedIncrement on unsigned integers without sacrificing anything.

For example, with 3 bits we have the following table:

raw bits | unsigned integer | twos complement signed integer
------------------------------------------------------------
000      |                0 |                             0 
001      |                1 |                             1 
010      |                2 |                             2 
011      |                3 |                             3 
100      |                4 |                            -4 
101      |                5 |                            -3
110      |                6 |                            -2
111      |                7 |                            -1

Incrementing by one (and taking overflow into account) is equivalent to moving down one entry in the table, in both cases. Note that this doesn't work for ones complement arithmetic, since the negatives are arranged in the opposite order.

you can declare the uint as volatile.

http://msdn.microsoft.com/en-us/library/x13ttww7(VS.71).aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top