下面的代码是可重入且线程安全的吗?
下面的代码是可重入的吗?
如果 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());
}
Is the following code is reentrant?
Is it thread-safe, if this.NextToExecuteIndex
is declared 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());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,这根本不是线程安全的。由于该对象是线程本地的,所以锁没有任何作用。它需要被所有调用线程共享。一旦解决了这个问题,您就不需要使用互锁增量,因为锁会串行执行。
作为一般规则,您应该将
locker
放置在与您要保护的资源相同的级别。如果资源由实例拥有,那么应该是locker
。同样,如果资源归类所有。至于可重入性,
lock
关键字使用可重入锁,即如果该线程持有该锁,则允许该线程进入。这可能不是你想要的。但如果你有一个不可重入锁,那么你只会因可重入调用而陷入死锁。我认为你也不会想要这样。你看起来想要一个环绕增量。只要集合不被修改,就可以通过互锁操作(即无锁)来实现。如果是这样,那么可以这样写:
注意:您应该将
NextToExecuteIndex
声明为易失性的。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. If the resource is owned by the instance then so should belocker
. Similarly if the resource is owned by the class.As for re-entrancy, the
lock
keyword uses a re-entrant lock, i.e. one that lets the same thread in if the lock is held by that thread. 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, i.e. lock free. If so then it can be written like this:
Note: You should declare
NextToExecuteIndex
as volatile.绝对不是。这是你的问题
object locker = new object();
。您将创建一个新对象并每次锁定它。Absolutely not. This is your problem
object locker = new object();
. You will create a new object and lock on it every time.