2014-02-20 1 views
2

У меня есть несколько потоков, которые нужно записать в очередь Azure. Чтобы увеличить пропускную способность, я создал 8 различных очередей Azure. В результате у меня есть 8 различных строк соединения, хранящихся в статическом массиве []. Я бы хотел написать код, который отлично загружает балансы, записывающие эти очереди, всегда возвращая индекс следующей очереди для записи в (и строку подключения для использования), так что очередь 0 записывается в то же количество раз, что и очередь 1, очередь 2 и т. Д. - все последовательно. Мне нужен способ итерации через индексы от 0 до 7, таким образом, чтобы поточно-безопасный. Есть ли более эффективный и эффективный способ написать приведенный ниже код и как сделать его потокобезопасным? Большое спасибо.Как вы выполняете итерацию по массиву индексов в потокобезопасном, эффективном образом?

private static int currentQueueIndex = -1; // initial value set to -1 so that index 0 is returned first. 
    private static int maxIndex = 7; 
    private static int GetNextQueueIndex() 
    { 
     int tempIndex = currentQueueIndex + 1; 
     if (tempIndex > maxIndex) 
     { 
      currentQueueIndex = 0; 
      return 0; 
     } 
     else 
     { 
      return tempIndex; 
     } 
    } 
+0

Я не считаю, что это поточно так, как вы есть. определить экземпляр простого объекта, а затем заблокировать этот экземпляр внутри GetNextQueueIndex, чтобы он был потокобезопасным. – LB2

+0

Вы просто увеличиваете int, я бы просто обернул его в 'lock'. – Blorgbeard

ответ

3

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

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

private static int GetNextQueueIndex() 
{ 
    return Interlocked.Increment(ref currentQueueIndex) & (maxIndex - 1); 
} 

Или, если у вас есть не-мощность из-два количества очередей - но вы просили перфорацию, поэтому я предлагаю избежать DIV:

private static int GetNextQueueIndex() 
{ 
    int i = Interlocked.Increment(ref currentQueueIndex) & Int32.MaxValue; 
    return i % maxIndex; 
} 

Примечания нет необходимости сброса currentQueueIndex обратно 0 - это совершенно безопасно, чтобы переполнение памяти и заклеить просто биты мы необходимость.

+0

Вы имели в виду% (modulo division)? – LB2

+0

'& 7' также работает, потому что 7 - 0b111, но% будет более четким. – Blorgbeard

+0

И это не сохраняет значение mod 7 .., которое может не иметь значения. – Blorgbeard

0

Благодаря @Cory Нельсон, следующее окончательное решение:

/// <summary> 
    /// This will return 0 through 7 continuously in a thread-safe manner. 
    /// </summary> 
    /// <returns>0, 1, 2, 3, 4, 5, 6, 7, and then back to 0.</returns> 
    private const int maxIndex = 7; // warning - must be a ([power-of-two number] - 1) 
    private static int currentQueueIndex = -1; 
    private static int GetNextQueueIndex() 
    { 
     return Interlocked.Increment(ref currentQueueIndex) & (maxIndex); 
    } 
Смежные вопросы