#1,100 – Increment and Decrement Operators Are Not Thread-Safe

If you have multiple threads increment or decrementing a variable using the increment or decrement operators, you may not get the desired result.  These operators are not thread-safe.

Imagine two threads that increment a variable.  If they do the operation serially, the variable ends up correctly incremented twice.  If the two threads read the value at the same time, however, they may both end up writing the same value back to the variable.  The variable ends up incremented just once.

You can do a safe increment operation using System.Threading.Threadlocked.Increment.

        private static int counter1 = 0;
        private static int counter2 = 0;

        static void Main(string[] args)
        {
            int maxExclusive = 1001;

            Parallel.For(1, maxExclusive, n =>
            {
                // Do some work here.
                Thread.Sleep(4);
                counter1++;
                Interlocked.Increment(ref counter2);
            });

            Console.WriteLine(
                "Ran {0} iterations, counter 1 = {1}, counter 2 = {2}",
                maxExclusive - 1, counter1, counter2);

            Console.ReadLine();
        }

Note below that Counter #1 is not incremented properly.
1100-001

Advertisements

#1,099 – Overloading the Increment Operator

You can overload the increment (++) operator in a class, providing custom increment functionality for an object.

The example below shows an overloaded increment operator defined in a Dog class.  The effect is to add 1 to the age of the dog.  We are careful to return a reference to the object that was passed in so that no other data in the instance changes.

    public class Dog 
    {
        // Increment a Dog
        public static Dog operator ++(Dog d)
        {
            d.Age++;
            return d;
        }

        public string Name { get; set; }
        public int Age { get; set; }
        public string Nickname { get; set; }

        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
            Nickname = "?";
        }

        public override string ToString()
        {
            return string.Format("{0}, Age {1}, Nickname [{2}]", Name, Age, Nickname);
        }
    }

We can use the operator as follows:

            Dog kirby = new Dog("Kirby", 10);
            kirby.Nickname = "Ball Chaser";
            Console.WriteLine(kirby);

            kirby++;
            Console.WriteLine(kirby);

1099-001

#54 – Increment and Decrement Operators

The increment operator (++) increments its operand by 1.  It’s a shorthand for using the binary + operator with an operand of 1.

 int n1 = 5;
 n1 = n1 + 1;     // Incrementing using +, n1 now 6
 n1++;            // Incrementing using ++, n1 now 7

You can also use the increment operator on the right-hand side of an expression.  In the example below, n1 is incremented after the expression is evaluated.

 n1 = 5;
 int n2 = 2 * n1++;   // n2 now 10, n1 is 6

Placing the ++ operator after the operand is known as postfix notation.  With prefix notation, the operator is placed before the operand, indicating the the variable should be incremented before the expression is evaluated.

 n1 = 5;
 n2 = 2 * ++n1;   // n2 now 12, n1 is 6

The decrement operator (- -) works similarly, decrementing the operand by 1.

 n1 = 5;
 n2 = 2 * n1--;   // n2 now 10, n1 is 4