-1

I have a simple class designed to play around with threading. It has a member variable, num, which is initialized to 0, and a method called modify which increments and then decrements num a high number of times. When the program runs, it creates two threads which both run modify, and then starts a timer and starts the threads. It uses a while loop to wait for both threads to finish executing, and then stops the timer and prints the time elapsed to the console. The class:

public class Threading
{

    public static void Main()
    {
        Threading t = new Threading();
        t.demo();
    }

    private int num = 0;

    public void doThreading()
    {

        Thread t1 = new Thread(modify);
        Thread t2 = new Thread(modify);

        t1.Start();
        t2.Start();

        Stopwatch timer = new Stopwatch();
        timer.Start();

        while (thread1.IsAlive || thread2.IsAlive)
        {

        }

        timer.Stop();
        Console.WriteLine("Took: " + timer.ElapsedMilliseconds + " milliseconds");

        Console.Read();
    }

    public void modify()
    {
        for (int i = 0; i < 1000000000; i++)
        {
            count++;
            count--;
        }
    }
}

After running the program, num will not be 0 because of race conditions. When I add locks to the modify method so that num is 0 after running the program:

public void modify()
    {
        for (int i = 0; i < 1000000000; i++)
        {
            lock (this) { count++; }
            lock (this) { count--; }
        }
    }

Then the program takes 8 times as long to execute. I cannot figure out why it would be taking so much longer, I would expect, at most, for it to take 4 times as long to execute. Any idea why it is taking so much longer?

E. Johnson
  • 19
  • 2
  • Lol, why do you expect 4, but not 8? :) Why do you select 4, not 5, not 2, not 11? It's weird to expect this. – Backs Nov 16 '17 at 06:15
  • My understanding of multithreading and locks is very limited, I would think that since there are 2 threads, and 2 segments of code, both of which are in separate locks, the slowdown would be by a factor of 2. I wasn't really thinking about overhead from accessing locks, just the cost of forcing threads to wait for each other, but I guess with such simple code the overhead from the accessing the locks could be pretty significant – E. Johnson Nov 16 '17 at 06:30
  • Well, wrong question. It should be "how can `lock` be so astonishingly efficient?" – Hans Passant Nov 16 '17 at 08:24

1 Answers1

1

lock can appear to be quite expensive in such a case (all you want is to lock incrementing an int, i.e. make count++ atomic); use Interlocked instead:

public void modify()
{
    for (int i = 0; i < 1000000000; i++)
    {
        Interlocked.Increment(ref count);
        Interlocked.Decrement(ref count); 
    }
}
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215