Является ли следующий код реентерабельным и поточно-ориентированным? - PullRequest
1 голос
/ 05 октября 2011

Является ли следующий код реентерабельным?

Является ли потокобезопасным, если this.NextToExecuteIndex объявлено private int NextToExecuteIndex = 0; и не рассчитано где-либо еще?

    protected override void Poll(object sender, System.Timers.ElapsedEventArgs e)
    {
        int index;

        object locker = new object();

        lock (locker)
        {
            Interlocked.Increment(ref this.NextToExecuteIndex);

            if (this.NextToExecuteIndex >= this.ReportingAgentsTypes.Count())
            {
                this.NextToExecuteIndex = 0;
            }

            index = this.NextToExecuteIndex;
        }

        var t = this.ReportingAgentsTypes[index];

        Console.WriteLine(t.ToString());
    }

Ответы [ 2 ]

8 голосов
/ 05 октября 2011

Нет, это не потокобезопасность вообще. Блокировка не имеет никакого эффекта, так как объект является локальным для потока. Это должно быть общим для всех вызывающих потоков. Как только вы исправите это, вам не нужно использовать блокированное приращение, потому что блокировка сериализует выполнение.

Как правило, вы должны размещать locker на том же уровне, что и ресурс, который вы защищаете. Если ресурс принадлежит экземпляру, тогда должно быть locker. Аналогично, если ресурс принадлежит классу.

Что касается повторного входа, ключевое слово lock использует блокировку повторного входа, то есть такую, которая пропускает тот же поток, если блокировка удерживается этим потоком. Это, вероятно, не то, что вы хотите. Но если бы у вас была не входящая блокировка, вы бы просто заблокировали себя повторным входящим вызовом. И я не думаю, что вы тоже этого захотите.

Ты выглядишь так, как будто хочешь обернуть шаг за шагом Пока коллекция не изменяется, это может быть достигнуто с помощью блокированных операций, то есть без блокировки. Если так, то это можно записать так:

do
{
    int original = this.NextToExecuteIndex;
    int next = original+1;
    if (next == this.ReportingAgentsTypes.Count())
        next = 0;
}
while (Interlocked.CompareExchange(ref this.NextToExecuteIndex, next, original) != original);

Примечание: Вы должны объявить NextToExecuteIndex как изменчивый.

4 голосов
/ 05 октября 2011

Абсолютно нет.Это твоя проблема object locker = new object();.Вы создадите новый объект и будете блокировать его каждый раз.

...