0

In this case, I define dirty read as reading from memory when it's currently being written to by another thread.

So if thread #1 writes 100 to a variable that thread #2 can also see, that writes 50 to the same variable, where both threads do so in a loop.

Is it possible to read the variable and get a number that is neither 50 or 100? Using no locks etc for sync.

More detail about my setup: Intel i3 CPU, I'm programming in C#.

Below is an example of what I mean:

using System;
using System.Collections.Generic;
using System.Threading;

namespace Threading001
{
    class Program
    {
        static void Main(string[] args)
        {
            long min = long.MinValue;
            long max = long.MaxValue;
            object number = max;

            new Thread(() =>
            {
                long current2 = (long)number;
                if (current2 != min && current2 != max)
                {
                    Console.WriteLine("Unexpected number from thread 2: {0}.", current2);
                }
                number = min;
            }).Start();

            while (true)
            {
                long current = (long)number;
                if (current != min && current != max)
                {
                    Console.WriteLine("Unexpected number from thread 1: {0}.", current);
                }
                number = max;
            }

        }
    }
}

I made number an object so the memory is allocated on the heap and not the stack to try and increase memory access latency times. Althrough cpu caching will probably stop that anyway.

user1515024
  • 181
  • 9

4 Answers4

2

You're actually trying to rely on several different things here.

Firstly, there's the matter of atomicity. ECMA-335 states:

A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size (the size of type native int) is atomic (see §I.12.6.2) when all the write accesses to a location are the same size. Atomic writes shall alter no bits other than those written. Unless explicit layout control (see Partition II (Controlling Instance Layout)) is used to alter the default behavior, data elements no larger than the natural word size (the size of a native int) shall be properly aligned. Object references shall be treated as though they are stored in the native word size.

So for a 32-bit integer, you're always fine - and for a 64-bit integer, you're fine if you're running on a 64-bit CLR... assuming your variables are aligned, which they are normally.

However, you've also got boxing involved - I don't think that will actually cause any problems here, but it does mean you're dealing with the visibility of multiple writes: one for the number variable itself, and one for the data within the box. With the .NET implementation, I believe that's still safe due to the stronger memory guarantees it provides - I wouldn't like to absolutely guarantee that it's safe within the ECMA memory model.

Finally, there's the matter of whether a write is visible or not, which is beyond atomicity. If thread T1 changes an int value from 0 to 100, then thread T2 reads it, atomicity guarantees that T2 will see either 0 or 100, never some other bit pattern - but there usually has to be some kind of memory barrier involved to guarantee that T2 will actually see the new value instead of a stale value. This is a really complex area - if you want to know more, I suggest you start with Joe Duffy's 2007 blog post and work from there.

Note that min, max and number will be on the heap anyway, as they've been captured by your lambda expressions... although the stack/heap is an implementation detail.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

It depends what the variable is (and what processor etc.etc.), but generally:
Yes, dirty reads are possible.

deviantfan
  • 11,268
  • 3
  • 32
  • 49
0

I am not familiar with details of your specific CPU but in general it depends on whether or not the READ/WRITE is atomic, which in turn depends on the architecture and how the variable is stored.

If the variable has larger size than CPU word size, it may not be atomic.

Modern cpu may guarantee atomic access to aligned memory address; if it needs more consideration if it has no HW support for misaligned memory access. If misaligned memory access is handled by software, the read or write would not be atomic: one load/store may lead to actually two operations. One example is PowerPC/Linux where kernel handles misaligned memory access in the exception handler.

tristan
  • 4,235
  • 2
  • 21
  • 45
0

this is all about thread safe or not it depends on datatype of that variable you want to read, some types such as long, int, byte etc are thread safe and you can read and write them in multiple threads.

you can find more information here

http://msdn.microsoft.com/en-us/library/dd997305(v=vs.110).aspx

Are primitive data types in c# atomic (thread safe)?

What is thread safe (C#) ? (Strings, arrays, ... ?)

Community
  • 1
  • 1
Jack Gajanan
  • 1,596
  • 14
  • 18