Question

I have some code which is its simplest form does the following.

float result = RunSimulation();
totalResult += result;

If I run this in a single thread I get different results compared to running it in multiple threads. If I put a lock around the totalResult addition then I get the same result but at a massive performance cost.

With floats being 32 bit I thought that operations on them were guaranteed to be atomic, so I don't understand why threading this is giving me different results.

I can just use ThreadStatic fields to keep count of to totals and then add them together with locks when the threads terminate, so it's not a solution that I'm looking for, just an explanation.

I wrote some test code to check this in it's simplest form. This code is as follows and also produces different results for every run.

class Program
{
    static float total;
    static int threadCount;

    static void Main(string[] args)
    {
        while (true)
        {
            total = 0;
            for (int i = 0; i < 10; i++)
                new Thread(ThreadMethod).Start();

            do
            {
                Thread.Sleep(10);
            } while (threadCount > 0);

            Console.WriteLine(total);
            if (Console.ReadKey(true).Key == ConsoleKey.Escape)
                break;
        }
    }

    static void ThreadMethod()
    {
        threadCount++;
        for (int i = 0; i < 100000; i++)
            total = total + 1.234f;

        threadCount--;
    }
}
Was it helpful?

Solution

Reading and writing floats is atomic, this is guaranteed by the language. However, operations on floats are not atomic. There is no way around using some kind of syncing in this case.

On a sidenote, you have a small race condition, the while might exit before any thread was ever started.

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