Заявление о блокировке, очевидно, не защищает критический код

Проблема: я использую оператор блокировки C # для защиты моей переменной '_NextId', когда я увеличиваю ее и присваиваю ее новое значение. Я не хочу, чтобы какие-либо другие потоки прерывали и зацепляли значение, пока приращение не завершилось.

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

Вот код, который не работает должным образом:

public class Widget {
    private static int _NextId;
    private object _LockToken = new object();

    public Widget() {
        //I expected this lock to prevent any other thread from assigning its ID until we have
        //completed incrementing the member variable
        lock (_LockToken) {
            ID = ++_NextId;
        }
    }

    public int ID { get; private set; }
}

Вот ссылка на DotNetFiddle, которая доказывает, что дубликаты создаются. Я интерпретирую этот результат как указание на то, что блокировка работает не так, как я ожидал. Скрипка DotNet запускает приведенный выше код в параллельном цикле, а затем подсчитывает, сколько дубликатов было создано. Если вы запустите его, он напечатает сообщение, показывающее количество дубликатов.

Всего 2 ответа


Вы должны объявить переменную _LockToken как static чтобы гарантировать, что блокировки сняты для одного и того же объекта.


В вашем коде для каждого виджета создается отдельный _LockToken .

Попробуйте добавить static модификатор в _LockToken , чтобы все экземпляры класса Widget ссылались на один и тот же «токен блокировки».


Есть идеи?

10000