Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoResetEvent vs. boolean to stop a thread

I have an object in a worker thread, which I can instruct to stop running. I can implement this using a bool or an AutoResetEvent:

boolean:

private volatile bool _isRunning;

public void Run() {
    while (_isRunning)
    {
        doWork();
        Thread.Sleep(1000);
    }
}

AutoResetEvent:

private AutoResetEvent _stop;

public void Run() {
    do {
        doWork();
    } while (!_stop.WaitOne(1000));
}

The Stop() method would then set _isRunning to false, or call _stop.Set().

Apart from that the solution with AutoResetEvent may stop a little faster, is there any difference between these method? Is one "better" than the other?

like image 368
Sjoerd Avatar asked Aug 14 '12 13:08

Sjoerd


1 Answers

C# volatile does not provide all the guaranties. It may still read stale data. Better to use underlying OS synchronisation mechanism as it provides much stronger guaranties.

All this in great depth discussed by Eric Lippert (really worth reading), here is short quote:

In C#, "volatile" means not only "make sure that the compiler and the jitter do not perform any code reordering or register caching optimizations on this variable". It also means "tell the processors to do whatever it is they need to do to ensure that I am reading the latest value, even if that means halting other processors and making them synchronize main memory with their caches".

Actually, that last bit is a lie. The true semantics of volatile reads and writes are considerably more complex than I've outlined here; in fact they do not actually guarantee that every processor stops what it is doing and updates caches to/from main memory. Rather, they provide weaker guarantees about how memory accesses before and after reads and writes may be observed to be ordered with respect to each other. Certain operations such as creating a new thread, entering a lock, or using one of the Interlocked family of methods introduce stronger guarantees about observation of ordering. If you want more details, read sections 3.10 and 10.5.3 of the C# 4.0 specification.

Frankly, I discourage you from ever making a volatile field. Volatile fields are a sign that you are doing something downright crazy: you're attempting to read and write the same value on two different threads without putting a lock in place. Locks guarantee that memory read or modified inside the lock is observed to be consistent, locks guarantee that only one thread accesses a given hunk of memory at a time, and so on.

like image 169
oleksii Avatar answered Sep 28 '22 10:09

oleksii