2

In most cases double and decimal type update on 64 bit system is an atomic operation cause these types are 64 bit. (decimal is 128bit so this is wrong, thanks for comments)

But when I update double? and decimal? type on 64 bit system will it be atomic? What is the size of double? and decimal?

I understand that atomicity is not guaranteed though I still interested if such update will be atomic in general scenario.

Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • 4
    in any circumstance when atomicity is being discussed, it is **critical** what is *guaranteed*. If (as you state) atomicity is not guaranteed, then frankly **that is the end of the discussion**. Anything past that is moot and irrelevent: you can't trust it, so don't use it. – Marc Gravell Nov 13 '12 at 14:02
  • A `Decimal` in .NET is 128 bits, not 64 bit. Updating a `decimal` on a 64bit system is therefore **not** atomic. – Steven Nov 13 '12 at 14:06
  • Technically, even the update to `double` is not guaranteed. I would probably use `Interlocked` to talk **even to that** - or a `lock` etc. – Marc Gravell Nov 13 '12 at 14:08
  • @MarcGravell disagree. atomicity is guaranteed on my server using particular OS and particular framework version and particular application. If this is the only scenario i'm going to use the application why not benefit from atomicity? – Oleg Vazhnev Nov 13 '12 at 17:34
  • @javapowered and who made you that guarantee? You won't find it in the language spec. What you mean is: "I deduce this is ok" - that is ***not*** a guarantee – Marc Gravell Nov 13 '12 at 18:26

3 Answers3

11

In most cases double and decimal type update on 64 bit system is atomic operation cause these types are 64 bit.

No, decimal is 128 bit to start with. Also note that running on a 64-bit computer doesn't necessarily mean you're running the 64-bit CLR. It's not clear what you mean by "system" here.

So you shouldn't even assume atomicity for decimal. Even on a 64-bit CLR, I wouldn't want to rely on the atomicity of double, partly as it will depend on alignment. The C# specification explicitly states (section 5.5 of the C# 4 spec):

Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic.

So that makes the nullable side kinda pointless, but...

But when I update double? and decimal? type on 64 bit system will it be atomic? what is the size of double? and decimal?

Nullable<T> is basically a T field and a bool field. So the storage will be more than 64 bits for double, and more than 128 bits for decimal. The exact storage will quite possibly depend on the context, but basically I wouldn't expect atomicity for operations with these types.

As others have said, you almost certainly don't want to rely on anything that's not guaranteed. Personally I'd almost always try to avoid lock-free coding in general. Try to use higher-level abstractions that are provided by the CLR/BCL teams and proven to be safe.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • "Personally I'd almost always try to avoid lock-free coding in general." - spoilsport ;p (that is tongue in cheek; when I delve into lock-free, I take a strong coffee first) – Marc Gravell Nov 13 '12 at 14:09
  • 1
    I am curious though, if you are running on an x86 CPU, as a 64bit process, are 64 bit value types / structs atomically written? C# specification is deliberately loose, but I don't see why in a 64bit x86 context it wouldn't be atomic. – M Afifi Nov 13 '12 at 14:45
  • Sorry about `decimal`. Ok on my system (HP DL360p-Gen8, Windows Server 2008 R2, .NET Framework 4.5) `double` update IS atomic. and `double?` update is NOT atomic? I just need to know how things work *on*my*particular*configuration. I do not need portability, i need speed. As speed = money for me and portability = nothing. – Oleg Vazhnev Nov 13 '12 at 17:39
  • also I was using `double?` in my system prety intensive without any locks. As `double?` type is more than 64 bit than it just can not be atomic, right? I just wonder how my system works then without any problems. Any chance to have `double?` update atomic? Probably I just need to write the test... – Oleg Vazhnev Nov 13 '12 at 17:42
  • Given that reads and writes of long, ulong, double, and decimal are not atomic, what happens when you try to read and write them at the same time in multiple threads *without locking*? Can you actually read out nonsensical values or completely fail a read/write (resulting in an immediate Exception)? – Kal Jul 15 '15 at 01:29
  • @Kal: In theory you could read values that haven't been written (not necessarily "nonsensical" ones, just ones with part of one value and part of another). Actually demonstrating this phenomenon (known as "tearing") is likely to be tricky - you could probably do it more easily with your own very large custom struct. – Jon Skeet Jul 15 '15 at 06:05
  • @JonSkeet Is it possible that assignment to a Nullable would be thread-safe by accident? I used ILSpy to look at the decompiled source code of Nullable and there's an implicit conversion, which means that every time you assign to a Nullable, you are actually creating a new Nullable first, instead of overwriting the internal value in the existing Nullable. Now, because Nullable is not your run-of-the-mill struct (it can be null), is it possible that the CLR actually uses a pointer or address for it, which is in fact updated atomically? – Kal Jul 15 '15 at 10:43
  • @JonSkeet I also wrote a simple WPF program to test the tearing effect on a ulong. It was really easy to get the tearing with a regular ulong, but so far I have had no luck getting tearing with a Nullable. – Kal Jul 15 '15 at 10:44
4

I understand that atomicity is not guaranteed

That's it. It is not guaranteed.

I still interested if such update will be atomic in general scenario.

It is not guaranteed.

Just like Marc said.

Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • i've learned that using HP DL360p-Gen 8, Windows Server 2008 R2 and .NET Framework 4.5 atomicity is guaranteed. This is the only scenario I need. – Oleg Vazhnev Nov 13 '12 at 17:36
  • @javapowered - That is far from what you described in your question, and it is still **not** guaranteed. That it appears to work atomically, doesn't make it so. – Oded Nov 13 '12 at 17:45
  • Of course it is guaranteed on *this* configuration. You will not be able to run it *not* atomic on *this* configuration. – Oleg Vazhnev Nov 13 '12 at 18:18
  • @javapowered - What are you talking about? A `decimal` is 128 bits - operations on it _cannot_ be atomic on a 64bit architecture. Where exactly did you get this guarantee? Who from? – Oded Nov 13 '12 at 18:25
  • I'm talking about 64-it types such as `double`. I've made a mistake in my initial question. – Oleg Vazhnev Nov 13 '12 at 19:33
  • @javapowered - I did answer the original question, so in that respect, the answer is still correct. It is also correct in regards to nullables. – Oded Nov 13 '12 at 19:34
1

C# specificaiton allows it to write a 64 bit variable as two 32 bit variables.

The C# language reserves the right to make writing to a long equivalent to writing to two ints, one after the other, and in practice some chips do implement it that way

See more for Eric Lippert here

Community
  • 1
  • 1
M Afifi
  • 4,645
  • 2
  • 28
  • 48