以下代码是否可重入且线程安全

本文关键字:线程 安全 代码 是否 | 更新日期: 2023-09-27 18:10:26

以下代码是可重入的吗?

它是线程安全的,如果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());
    }

以下代码是否可重入且线程安全

不,这根本不是线程安全的。锁没有作用,因为对象是线程的本地对象。它需要被所有调用线程共享。一旦你解决了这个问题,你就不需要使用互锁增量了,因为锁会序列化执行。

作为一般规则,您应该将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为易失性

绝对不行。这是你的问题object locker = new object();。您将创建一个新对象并每次锁定它。