Feb 19 2010

What the heck is a torn-read?

If you've written any high performance asynchronous applications you may have found yourself putting up Memory Barriers to avoid those costly thread locks. More commonly known as Memory Fences, this technique can allow you to create lock-free read-modify-write operations which can give you that little extra bit of performance that some applications need. To be fair this is an advanced technique so if you are embarking on this sort of thing be very careful and do lots of testing.

The problem with using lock-free approaches is that you now have to deal with Atomicity on your own and this may not always be as straightforward as you might think. Lets look at a couple simple examples of what is and is not Atomic.

Single reads and writes are always atomic:

Int32 number = 123; /* single writes are atomic */
number.ToString(); /*single reads are atomic */

Unary operations are another story since they consist of two operations (one read and one write). As a result, using them in a lock-free environment can lead to unexpected results:

number += 2;

This means that another thread or process could alter the value of 'number' in between its read and write. When this happens you will certainly be left scratching your head wondering how 1+= 1 could possibly equal 1294.

64 Bit types present an even more subtle problem. Single reads or writes of 64 Bit types 'may' not be atomic the same way their 32 Bit counterparts are. Thats right, I said 'may' not... Here's the issue. To store a 64 Bit value in a 32 Bit environment the runtime needs two separate memory locations and consequently there are two separate instructions to read or write a value. This creates a vulnerability similar to unary operations called a torn-read. When this occurs one of the memory locations reflects a value from one thread or process while the other reflects a value from another thread or process. In the end, this will cause you no end of pain and is next to impossible to debug.

Thread or Process A writes 5,000,000,000 which is stored in two 32 bit registers as follows:

10101010000001011111001000000000 -- 10101010000001011111001000000000

Thread or Process B writes 10,000,000,000 which is stored in the same two 32 bit registers as follows:

11010100000010111110010000000000 -- 11010100000010111110010000000000

A read by either could result in the following combination:

10101010000001011111001000000000 -- 11010100000010111110010000000000

In 64 Bit environments this is not an issue because they only need one memory location and can read and write with only one instruction.

So how can you use a lock-free pattern and avoid this problem on 32-bit platforms? There are a couple ways to deal with this, but really only one worth mentioning... Interlocked.

Interlocked.Increment(ref number);

This class provides a number of methods to help ensure interaction with types such as these are done atomically.

So what is the moral of this story?  If you are going lock-free... Test, test, test...

Tags: ,


trackback DotNetKicks.com says:

What the heck is a torn-read?

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Tennie Unkn Tennie Unkn United States says:

Our team's practice is that severity is the degree of technical affect while priority is the level of business organization impact. The tester may mark an original value to priority, but finally the final decision on priority is owned by the business collaborator. Also, we endeavour to set definitions for severity that provide little way for debate, while the definitions for priority are more flexible and responsive to business need.

tarcica iglasta tarcica iglasta Poland says:

Thanks for good article. Hope to see more soon.

Hyacinth Molzahn Hyacinth Molzahn says:

Fantastic post! This could aid lots of people find out about this matter. Do you want to incorporate video clips together with these? It could undoubtedly help out. Your reason was spot on and owing to you; I probably won't have to describe everything to my pals. I can simply direct them here

Agustin Zastawny Agustin Zastawny United States says:

Well said, you just earned another subscriber

Jelqing - Jelqs Jelqing - Jelqs United States says:

Great blog to read. I was really surprised actually because I thought I was going to take a lot of time to find information on this topic but your blog had it all. Thanks for the post and share. – Cheers - Nicole

Melinda Whitsey Melinda Whitsey United States says:

Hi webmaster - This is by far the best looking site I’ve seen. It was completely easy to navigate and it was easy to look for the information I needed. Fantastic layout and great content! Every site should have that. Awesome job

Vincent Sparkes Vincent Sparkes says:

It does seem that everybody is into this kind of stuff lately. Don’t really understand it though, but thanks for trying to explain it. Appreciate you shedding light into this matter. Keep it up

Lin Cheely Lin Cheely says:

Although I would’ve preferred if you went into a little bit more detail, I still got the gist of what you meant. I agree with it. It might not be a popular idea, but it makes sense. Will definitely come back for more of this. Great work

Clarence Culton Clarence Culton United States says:

This is certainly my initial stop by and I really like what I'm seeing. Your weblog is so much fun to look over, quite compelling as well as informative. I'll undoubtedly recommend it to my friends. Nevertheless, I did have some problem with the commenting. It kept giving me an problem whenever I clicked on publish comment. I hope, that can be fixed. Many thanks

pingback scoop.it says:

Pingback from scoop.it

Smelser.NET | What the heck is a torn-read? | S...

Comments are closed