Domanda

I want to increment an integer that gets incremented in a timer event handler and read by the main and other worker threads i-e one writer thread and multiple reader threads. will it be threadsafe?

I have a timer in my application that runs every 5 seconds

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

that I turn on like this MyClock.Change( 5000, 5000 );

If I increment an integer in the Ticker handler like this tickerCounter++;

Can I then do a read-only access from main thread or worker threads of the same application? Will it be thread safe? Is there any chance of the reader to read a partial value? or causing a threading exception?

È stato utile?

Soluzione

Incrementing like this

tickerCounter++;

in multiple threads, without locking, is not threadsafe. You can use the Interlocked class to perform lock-free, threadsafe incrementing.

If only a single thread is modifying the value, with many threads reading the value, then tickerCounter++ is threadsafe in the sense that no thread will ever suffer a partial read. Of course there is still a race condition, but even if you use Interlocked, there would be a race.

Altri suggerimenti

Firstly: read Eric Lippert's blog post: What is this thing you call "thread-safe"? It will change how you think about thread safety, and how you ask similar questions in the future.

The reads will be atomic - you'll never see "half" an update - but you won't necessarily see the latest value. (That means that the next increment may see an "old" (lower) value to increment, of course.)

Additionally, the increment itself isn't inherently safe - if there were several threads incrementing at the same time, they could all read the same value, then increment locally, then write the new value - so the result could be an increment of 1, even if 10 threads were incrementing.

You should consider using Interlocked.Increment to perform the increment. If you also make the variable volatile, I believe you should be safe just to read it directly when you only want to read it.

Perhaps you could use Interlocked.Increment(ref Int32) to do the incrementing? That does it as an atomic operation.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top