我想增加一个在计时器事件处理程序中递增的整数,并由主和其他工作线程读取,即一个编写器线程和多个读取器线程。它会线程安全吗?
我的应用程序中有一个每5秒运行一次的计时器
MyClock = new System.Threading.Timer(new TimerCallback(this.Ticker),null,Timeout.Infinite,Timeout.Infinite);
我打开了这样的话 MyClock.Change(5000,5000);如果我在Ticker处理程序中增加一个整数,就像这样 tickerCounter ++;
然后,我可以从同一应用程序的主线程或工作线程执行只读访问吗? 它是线程安全的吗?读者是否有机会阅读部分价值?或导致线程异常?
答案 0 :(得分:3)
首先:阅读Eric Lippert的博文:What is this thing you call "thread-safe"?这将改变您对线程安全的看法,以及您将来如何提出类似问题。
读取将是原子 - 您永远不会看到“一半”更新 - 但您不一定会看到最新值。 (这意味着下一个增量可能会看到要增加的“旧”(较低)值。)
此外,增量本身并不是安全的 - 如果有多个线程同时递增,它们都可以读取相同的值,然后在本地递增,然后写入新值 - 因此结果可能是一个增量为1,即使10个线程正在递增。
您应该考虑使用Interlocked.Increment
来执行增量。如果您也使变量变为volatile,我相信当您仅想要阅读它时,您应该直接阅读它。
答案 1 :(得分:2)
也许您可以使用Interlocked.Increment(ref Int32)
进行递增?这是一个原子操作。
答案 2 :(得分:1)
像这样增加
tickerCounter++;
在多个线程中,没有锁定,不是线程安全的。您可以使用Interlocked
类来执行无锁,线程安全递增。
如果只有一个线程正在修改该值,并且有许多线程在读取该值,那么tickerCounter++
是线程安全的,因为任何线程都不会遭受部分读取。当然还有竞争条件,但即使你使用Interlocked
,也会有竞争。