c#2.0是int32线程安全的吗?

c#2.0是int32线程安全的吗?,c#,thread-safety,int32,C#,Thread Safety,Int32,我想递增一个整数,该整数在计时器事件处理程序中递增,并由主线程和其他工作线程(即一个writer线程和多个reader线程)读取。它是线程安全的吗 我的应用程序中有一个计时器,每5秒运行一次 MyClock=new System.Threading.Timer(new TimerCallback(this.Ticker),null,Timeout.Infinite,Timeout.Infinite) 我就这样打开 MyClock.Change(5000,5000) 如果我像这样在Ticker处理

我想递增一个整数,该整数在计时器事件处理程序中递增,并由主线程和其他工作线程(即一个writer线程和多个reader线程)读取。它是线程安全的吗

我的应用程序中有一个计时器,每5秒运行一次

MyClock=new System.Threading.Timer(new TimerCallback(this.Ticker),null,Timeout.Infinite,Timeout.Infinite)

我就这样打开 MyClock.Change(5000,5000)

如果我像这样在Ticker处理程序中增加一个整数 tickerCounter++

然后我可以从同一应用程序的主线程或工作线程执行只读访问吗? 它是线程安全的吗?读者是否有机会读取部分值?或者导致线程异常?

您是否可以使用来执行递增操作?这是一个原子操作。

也许你可以用它来做递增运算?这是一个原子操作。

像这样递增

tickerCounter++;
在多线程中,如果没有锁定,则不是线程安全的。您可以使用
Interlocked
类执行无锁、线程安全的增量

如果只有一个线程正在修改该值,而许多线程正在读取该值,那么
tickerCounter++
是线程安全的,因为没有线程会遭受部分读取。当然,仍然存在竞争条件,但即使使用
联锁
,也会有竞争。

这样递增

tickerCounter++;
在多线程中,如果没有锁定,则不是线程安全的。您可以使用
Interlocked
类执行无锁、线程安全的增量


如果只有一个线程正在修改该值,而许多线程正在读取该值,那么
tickerCounter++
是线程安全的,因为没有线程会遭受部分读取。当然,仍然存在争用条件,但即使您使用
Interlocked
,也会存在争用。

首先:阅读Eric Lippert的博客文章:它将改变您对线程安全的看法,以及您将来如何问类似问题

读取将是原子的-您永远不会看到“一半”更新-但您不一定会看到最新的值。(这意味着下一个增量可能会看到要增量的“旧”(较低)值。)

此外,增量本身并不是天生安全的——如果有多个线程同时递增,它们都可以读取相同的值,然后在本地递增,然后写入新值——因此,即使有10个线程递增,结果也可能是递增1


你应该考虑使用它来执行增量。如果你也让变量不稳定,我相信当你只想读它的时候直接读它应该是安全的。

首先:阅读Eric Lippert的博客文章:它将改变你对线程安全的看法,以及你将来如何问类似的问题

读取将是原子的-您永远不会看到“一半”更新-但您不一定会看到最新的值。(这意味着下一个增量可能会看到要增量的“旧”(较低)值。)

此外,增量本身并不是天生安全的——如果有多个线程同时递增,它们都可以读取相同的值,然后在本地递增,然后写入新值——因此,即使有10个线程递增,结果也可能是递增1


你应该考虑使用它来执行增量。如果你也让变量不稳定,我相信当你只想读取它时,直接读取它应该是安全的。

thx,如果该值不是最新的,只要它不引发异常或提供半更新,对我来说就可以了。不遵循Jon的建议意味着有时你调用
tickerCounter++不会增加
ticketCounter
的值。
Interlocked.Increment
的文档中有演示此问题的示例代码。我觉得这样的决定会在以后造成很多混乱和浪费调试时间(或者1个月后别人调试你的代码,或者3个月后你调试你的代码)。@Brian虽然我当然不同意你所说的几乎所有事情,但只有一个线程在做增量。所有其他线程都在读,因此,您的第一句话不相关。@Marc:谁说只有一个线程在递增?它是一个没有同步对象的
System.Threading.Timer
,因此每次增量都会发生在线程池线程上,但每次都可能是不同的线程池线程。@JonSkeet我承认,你是对的。它可能(在多个计时器计时线程上同时执行增量)发生。thx,如果该值不是最新的,只要它不引发异常或提供半更新,对我来说就可以了。不遵循Jon的建议意味着有时您调用
tickerCounter++不会增加
ticketCounter
的值。
Interlocked.Increment
的文档中有演示此问题的示例代码。我觉得这样的决定会在以后造成很多混乱和浪费调试时间(或者1个月后别人调试你的代码,或者3个月后你调试你的代码)。@Brian虽然我当然不同意你所说的几乎所有事情,但只有一个线程在做增量。所有其他线程都在读,因此,您的第一句话不相关。@Marc:谁说只有一个线程在递增?它是一个没有同步对象的
System.Threading.Timer
,因此每次增量都会发生在线程池线程上,但每次都可能是不同的线程池线程。@JonSkeet我承认,你是对的。它可能(在多个计时器计时线程上同时执行增量)发生。