Are assignment of 4-byte quantities guaranteed atomic in the CLR?


We had a little thread on this internally today and I thought it interesting enough to share here.  I am just experimenting here – is this type of thing useful?


 


Q: If I do simple Int32 assignment to a shared variable in a CLR multi-threaded app, do I need to implement a lock.  The Interlocked class has many static methods, but no “assignment” (although Exchange works well enough — even if it seems a little kludgey).


 


A:  (From one of the senior architects on the CLR team)


The assignment will be atomic so long as the 4-byte quantity is 4-byte aligned.


 


If you allow the CLR to perform the layout (AutoLayout) then we will guarantee that alignment and hence the atomicity.  If you use ExplicitLayout or SequentialLayout, then you are responsible for alignment.  So long as you use the default packing, even SequentialLayout will guarantee good alignment.


 


Of course, guaranteeing an atomic update is not the same thing as guaranteeing that the other CPUs will immediately see the value you wrote.  Using Interlocked.Exchange will make this latter guarantee.


 


 


Update: A reader points out you can find more information about this in ECMA 335 spec (section: The Atomicity of Memory Accesses).

Comments (6)

  1. Tom Richards says:

    Comment on "is this type of thing useful". A definite YES from me. The more the better as far as I am concerned.

  2. Tom Richards says:

    Comment on "is this type of thing useful". A definite YES from me. The more the better as far as I am concerned.

  3. Brad Abrams says:

    I just heard from the .NET Compact Framework folks… and the same applies to netcf.

  4. Pooja says:

    I have an unrelated question.

    The 4 signature bytes in the beginning of a COR header in a managed exe or dll stand for the names of ??? BSJB translates into 4 core developers of CLR, I want to know the individual names.

    Thanks

  5. nkirchner says:

    Is this true in x86? I did a simple program and checked that the disassembly showed only a mov operation. So, I do not understand how the operation cannot be atomic:

    using System;
    using System.Runtime.InteropServices;

    namespace Align
    {
    class AlignTest
    {
    [StructLayout(LayoutKind.Explicit)]
    struct NotAligned
    {
    [FieldOffset(0)] public char Tmp;
    [FieldOffset(1)] public int Number;
    }

    [STAThread]
    static void Main(string[] args)
    {
    NotAligned na = new NotAligned();

    na.Tmp = ‘a’;
    // 00000019 mov word ptr [ebp-0Ch],61h
    na.Number = 5;
    // 0000001f mov dword ptr [ebp-0Bh],5 }
    }
    }

  6. Memory is usually a shared resource on multithreaded systems therefore access to it must be regulated