2014-03-18 8 views
2

Очевидный способ сделать это будет с блокировкой.Резьбовая левая смена

Но я знаю, что существует класс Interlocked в C#, что хорошо для приращения и уменьшения потока, поэтому я задавался вопросом, есть ли что-то подобное, что позволило бы мне сделать то же самое для двоичных операций, таких как сдвиг влево.

Есть что-нибудь вроде Interlocked класс для оператора с левым сменом?

+0

Оператора сдвига влево сам по себе является атомарной операцией. Чтобы уточнить, вы просите безопасный для потока способ сдвига влево и присваиваете значение? 'x = x << y;', правильно? – StriplingWarrior

+0

- это приращение и декремент. но при изменении значения несколькими потоками он работает неправильно –

+1

Вы всегда можете использовать 'Interlocked.CompareExchange' в цикле. – CodesInChaos

ответ

2

Предполагая, что вы пытаетесь сдвиг влево и назначить, и при условии, что вы не хотите столкновение, вы могли бы сделать что-то вроде этого:

// 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; 
    } 
} 
0

Методы Interlocked класса в основном ориентированы на предоставление поточно-безопасных версий отдельных операторов на C#. Он имеет методы для таких операторов, как += и ++, которые не являются потокобезопасными.

Многие операторы, такие как <<, =, и +, уже поточно-безопасны, поэтому для блокировки не существует методов. Как только вы объедините эти операторы с другими операторами (например, x = y + z), вы в значительной степени по своему усмотрению.

+0

Я не понимаю, почему '<<' более потокобезопасен, чем оператор '' '' '' '' ' –

+3

После того как вы добавите присвоение, операция больше не будет атомной. 'a = a << 1', конечно, не является атомарным. Поэтому, пока вы технически неправы, это не отвечает на вопрос. – CodesInChaos

+0

@ArsenZahray: '++' включает в себя загрузку, добавление и сохранение всего за одну операцию, тогда как '<<' - это просто загрузка и сдвиг влево. Вы должны объединить его с другим оператором, чтобы сохранить результат. – StriplingWarrior