Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
317 views
in Technique[技术] by (71.8m points)

c# - Why is there no overload of Interlocked.Add that accepts Doubles as parameters?

I fully appreciate the atomicity that the Threading.Interlocked class provides; I don't understand, though, why the Add function only offers two overloads: one for Integers, another for Longs. Why not Doubles, or any other numeric type for that matter?

Clearly, the intended method for changing a Double is CompareExchange; I am GUESSING this is because modifying a Double is a more complex operation than modifying an Integer. Still it isn't clear to me why, if CompareExchange and Add can both accept Integers, they can't also both accept Doubles.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Others have addressed the "why?". It is easy however to roll your own Add(ref double, double), using the CompareExchange primitive:

public static double Add(ref double location1, double value)
{
    double newCurrentValue = location1; // non-volatile read, so may be stale
    while (true)
    {
        double currentValue = newCurrentValue;
        double newValue = currentValue + value;
        newCurrentValue = Interlocked.CompareExchange(ref location1, newValue, currentValue);
        if (newCurrentValue == currentValue)
            return newValue;
    }
}

CompareExchange sets the value of location1 to be newValue, if the current value equals currentValue. As it does so in an atomic, thread-safe way, we can rely on it alone without resorting to locks.

Why the while (true) loop? Loops like this are standard when implementing optimistically concurrent algorithms. CompareExchange will not change location1 if the current value is different from currentValue. I initialized currentValue to location1 - doing a non-volatile read (which might be stale, but that does not change the correctness, as CompareExchange will check the value). If the current value (still) is what we had read from location, CompareExchange will change the value to newValue. If not, we have to retry CompareExchange with the new current value, as returned by CompareExchange.

If the value is changed by another thread until the time of our next CompareExchange again, it will fail again, necessitating another retry - and this can in theory go on forever, hence the loop. Unless you are constantly changing the value from multiple threads, CompareExchange will most likely be called only once, if the current value is still what the non-volatile read of location1 yielded, or twice, if it was different.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...