简体   繁体   English

以下代码可重入并且是线程安全的吗?

[英]Is the following code reentrant and thread-safe?

Is the following code is reentrant? 以下代码是可重入的吗?

Is it thread-safe, if this.NextToExecuteIndex is declared private int NextToExecuteIndex = 0; 如果this.NextToExecuteIndex被声明为private int NextToExecuteIndex = 0; ,则它是线程安全的private int NextToExecuteIndex = 0; and not computed anywhere else? 而不是在其他任何地方计算?

    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());
    }

No this is not thread-safe at all. 不,这根本不是线程安全的。 The lock has no effect since the object is local to the thread. 锁定无效,因为对象是线程本地的。 It needs to be shared by all calling threads. 它需要由所有调用线程共享。 Once you fix that you don't need to use interlocked increment because the lock serialises execution. 修复该问题后,您无需使用互锁增量,因为锁会序列化执行。

As a general rule you should place locker at the same level as the resource you are protecting. 通常,应将locker与要保护的资源置于同一级别。 If the resource is owned by the instance then so should be locker . 如果资源由实例拥有,则应为locker Similarly if the resource is owned by the class. 同样,如果资源归类所有。

As for re-entrancy, the lock keyword uses a re-entrant lock, ie one that lets the same thread in if the lock is held by that thread. 至于重入, lock关键字使用一个重入锁,即如果该线程持有该锁,则该锁允许同一线程进入。 That's probably not what you want. 那可能不是您想要的。 But if you had a non re-entrant lock then you would just deadlock yourself with a re-entrant call. 但是,如果您具有非重入锁,那么您将通过重入调用使自己陷入僵局。 And I don't think you'd want that either. 而且我也不认为您想要那样。

You look like you want a wrap around increment. 您看起来好像想要环绕增量。 So long as the collection is not being modified, this can be achieved with interlocked operations, ie lock free. 只要不修改集合,就可以通过互锁操作(即无锁)来实现。 If so then it can be written like this: 如果是这样,则可以这样写:

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);

Note: You should declare NextToExecuteIndex as volatile. 注意:您应该将NextToExecuteIndex声明为volatile。

Absolutely not. 绝对不。 This is your problem object locker = new object(); 这是您的问题。 object locker = new object(); . You will create a new object and lock on it every time. 您将创建一个新对象并每次都将其锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM