2

The obvious way to do it would be with locking.

But I know that there is Interlocked class in c#, which is good for thread safe increment and decrement, so I wondered if there is something like that which would let me do the same for binary operations like left shift.

Is there anything like Interlocked class for left-shift operator?

Arsen Zahray
  • 24,367
  • 48
  • 131
  • 224
  • The left-shift operator by itself is an atomic operation. Just to clarify, you're asking for a thread-safe way to left-shift and assign a value? `x = x << y;`, right? – StriplingWarrior Mar 18 '14 at 22:52
  • so is increment and decrement. but when modifying the value by multiple threads, it works incorrectly – Arsen Zahray Mar 18 '14 at 22:59
  • 1
    You can always use `Interlocked.CompareExchange` in a loop. – CodesInChaos Mar 18 '14 at 23:00
  • @ArsenZahray: Increment/decrement assign a value to the same variable that they load from, whereas left-shift does not make any assignment all by itself. Two threads can do `y = x << 1` in any order they want (and as many times as they want), and you'll always end up with the same value for `y`. But if they do `x = x << 1` then suddenly you're going to get different results if they each load `x` before either of them saves it. So `<<` is thread-safe by itself, but assigning any value based on some computation of its own value is not thread-safe. – StriplingWarrior Mar 18 '14 at 23:20

2 Answers2

2

Assuming you are trying to left-shift and assign, and assuming that you do not want collisions, you could do something like this:

// this method will only return a value when this thread's shift operation "won" the race
int GetNextValue()
{
    // execute until we "win" the compare
    // might look funny, but you see this type of adjust/CompareAndSwap/Check/Retry very often in cases where the checked operation is less expensive than holding a lock
    while(true)
    {
        // if AValue is a 64-bit int, and your code might run as a 32-bit process, use Interlocked.Read to retrieve the value.
        var value = AValue;
        var newValue = value << 1;
        var result = Interlocked.CompareExchange(ref AValue, newValue, value);
        // if these values are equal, CompareExchange peformed the compare, and we "won" the exchange
        // if they are not equal, it means another thread beat us to it, try again.
        if (result == value)
            return newValue;
    }
}
JMarsch
  • 21,484
  • 15
  • 77
  • 125
0

The Interlocked class's methods are largely focused on providing thread-safe versions of individual operators in C#. It has methods for operators like += and ++, which are not thread safe.

Many operators, like <<, =, and +, are thread-safe already, so Interlocked doesn't have methods for those. Once you combine those operators with other operators (like x = y + z), you're pretty much on your own.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 3
    Once you add the assignment the operation won't be atomic anymore. `a = a << 1` certainly isn't atomic. So while you're technically not wrong, it doesn't answer the question. – CodesInChaos Mar 18 '14 at 23:01
  • @ArsenZahray: `++` involves a load, add, and save, all in one operation, whereas `<<` is just a load and left-shift. You have to combine it with another operator in order save the result. – StriplingWarrior Mar 18 '14 at 23:13
  • @CodesInChaos: I felt it answered the question fairly well. The question is whether there is an `Interlocked` class [or method] for the left-shift operator. I explained that there is not, and went beyond that to explain why the .NET framework developers likely felt that this was not an omission. – StriplingWarrior Mar 18 '14 at 23:25