Xenoprimate
Xenoprimate

Reputation: 7963

Atomic Operation Thread Safety - Do I Need a "Mirror" Atomic Read?

Is the following code safe (considering it in isolation) from a torn read?

private static double flopsErrorMargin = 0.01d;

public static double FlopsErrorMargin {
    get {
        double result = flopsErrorMargin;
        Thread.MemoryBarrier();
        return result;
    }
    set {
        Interlocked.Exchange(ref flopsErrorMargin, value);
    }
}

The atomic write operation (Interlocked.Exchange()) is required because a double is not guaranteed to be written in a single operation on the .NET platform (excepting implementation details on 64-bit environments).

However, do I also need a 'mirror' operation on the read side? E.g. am I still at risk of getting a torn read because I do not read the value atomically?

My hunch is that I will not, because I think that another memory access (e.g. a read) can not happen concurrently with any other atomic operation, even if that other access is not itself atomic. But I would like some confirmation!

Upvotes: 3

Views: 145

Answers (2)

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73452

No, Torn reads are possible. Assume your field access is reading the data and interleaved partway by the Interlocked.Exchange, then other 32 bits will be the updated value of Exchange and thus produces torn read.

For atomic read, you need to use Interlocked.Read (in 32 bit machines).

The Read method is unnecessary on 64-bit systems, because 64-bit read operations are already atomic. On 32-bit systems, 64-bit read operations are not atomic unless performed using Read

Which also means that torn values are possible.

You could define your own atomic Read for double as follows

public static double Read(ref double location)
{
    return Interlocked.CompareExchange(ref location, 0d, 0d);
}

This is how Interlocked.Read(long) is implemented internally.

Upvotes: 3

Servy
Servy

Reputation: 203811

am I still at risk of getting a torn read because I do not read the value atomically?

Yes. The return value of Interlocked.Exchange won't be torn, and the value that flopsErrorMargin eventually ends up as will be value (those are the two guarantees that Interlocked.Exchange give you), but an unsynchronized read access could be torn.

Upvotes: 2

Related Questions