锁定语句显然没有保护关键代码

Lock Statement Apparently Not Protecting Critical Code

问题:我正在使用 C# lock 语句 来保护我的变量“_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; }
}

这里有一个 link 到 DotNetFiddle 证明创建了重复项。我将该结果解释为表明锁没有按我预期的方式工作。 DotNet fiddle 运行 在并行循环中使用上面的代码,然后计算创建了多少重复 ID。如果你 运行 它,它会打印一条消息显示重复计数。

您应该将 _LockToken 变量声明为 static 以确保锁定是针对同一对象的。

在您的代码中,正在为每个小部件创建一个不同的 _LockToken

尝试向 _LockToken 添加 static 修饰符,这样 Widget class 的所有实例都引用相同的 "lock token".