I'm trying to understand thread-safe access to fields. For this, i implemented some test sample:
class Program
{
public static void Main()
{
Foo test = new Foo();
bool temp;
new Thread(() => { test.Loop = false; }).Start();
do
{
temp = test.Loop;
}
while (temp == true);
}
}
class Foo
{
public bool Loop = true;
}
As expected, sometimes it doesn't terminate. I know that this issue can be solved either with volatile keyword or with lock. I consider that i'm not author of class Foo, so i can't make field volatile. I tried using lock:
public static void Main()
{
Foo test = new Foo();
object locker = new Object();
bool temp;
new Thread(() => { test.Loop = false; }).Start();
do
{
lock (locker)
{
temp = test.Loop;
}
}
while (temp == true);
}
this seems to solve the issue. Just to be sure i moved the cycle inside the lock block:
lock(locker)
{
do
{
temp = test.Loop;
}
while (temp == true);
}
and... the program does not terminates anymore.
It is totally confusing me. Doesn't lock provides thread-safe access? If not, how to access non-volatile fields safely? I could use VolatileRead(), but it is not suitable for any case, like not primitive type or properties. I considered that Monitor.Enter does the job, Am i right? I don't understand how could it work.
This piece of code:
do
{
lock (locker)
{
temp = test.Loop;
}
}
while (temp == true);
works because of a side-effect of lock: it causes a 'memory-fence'. The actual locking is irrelevant here. Equivalent code:
do
{
Thread.MemoryBarrier();
temp = test.Loop;
}
while (temp == true);
And the issue you're trying to solve here is not exactly thread-safety, it is about caching of the variable (stale data).
It does not terminate anymore because you are accessing the variable outside of the lock as well.
In
new Thread(() => { test.Loop = false; }).Start();
you write to the variable outside the lock. This write is not guaranteed to be visible.
Two concurrent accesses to the same location of which at least one is a write is a data race. Don't do that.
Lock provides thread safety for 2 or more code blocks on different threads, that uses the lock.
Your Loop assignment inside the new thread declaration is not enclosed in lock.
That means there is no thread safety there.
In general, no, lock is not something that will magically make all code inside it thread-safe.
The simple rule is: If you have some data that's shared by multiple threads, but you always access it only inside a lock (using the same lock object), then that access is thread-safe.
Once you leave that “simple” code and start asking questions like “How could I use volatile/VolatileRed() safely here?” or “Why does this code that doesn't use lock properly seem to work?”, things get complicated quickly. And you should probably avoid that, unless you're prepared to spend a lot of time learning about the C# memory model. And even then, bugs that manifest only once in million runs or only on certain CPUs (ARM) are very easy to make.
Locking only works when all access to the field is controlled by a lock. In your example only the reading is locked, but since the writing is not, there is no thread-safety.
However it is also crucial that the locking takes place on a shared object, otherwise there is no way for another thread to know that someone is trying to access the field. So in your case when locking on an object which is only scoped inside the Main method, any other call on another thread, would not be able to block.
If you have no way to change Foo, the only way to obtain thread-safety is to have ALL calls actually lock on the same Foo instance. This would generally not be recommended though, since all methods on the object would be locked.
The volatile keyword is not a guarantuee of thread-safety in itself. It is meant to indicate that the value of a field can be changed from different threads, and so any thread reading that field, should not cache it, since the value could change.
To achieve thread-safety, Foo should probably look something along these lines:
class Program
{
public static void Main()
{
Foo test = new Foo();
test.Run();
new Thread(() => { test.Loop = false; }).Start();
do
{
temp = test.Loop;
}
while (temp == true);
}
}
class Foo
{
private volatile bool _loop = true;
private object _syncRoot = new object();
public bool Loop
{
// All access to the Loop value, is controlled by a lock on an instance-scoped object. I.e. when one thread accesses the value, all other threads are blocked.
get { lock(_syncRoot) return _loop; }
set { lock(_syncRoot) _loop = value; }
}
public void Run()
{
Task(() =>
{
while(_loop) // _loop is volatile, so value is not cached
{
// Do something
}
});
}
}
Related
My code seens to be allowing more than one thread to get into a specific method "protected" by mutex.
private static Mutex mut = new Mutex();
public DadoMySql PegaPrimeiroFila(int identificacao)
{
DadoMySql dadoMySql = null;
mut.WaitOne();
dadoMySql = PegaPrimeiroFila_Processa();
mut.ReleaseMutex();
return dadoMySql;
}
I have 10 threads and a keep getting 2 random ones of than getting the same "dadoMySql" everytime.
If i add logs inside de mutex wait everything works fine. The extra time it takes to write the log makes it work :/, maybe?
Mutex is overkill here, unless you are synchronizing across multiple processes.
A simple lock should work since you want mutual exclusion:
private static readonly object lockObject = new object();
public DadoMySql PegaPrimeiroFila(int identificacao)
{
DadoMySql dadoMySql = null;
lock (lockObject)
{
dadoMySql = PegaPrimeiroFila_Processa();
}
return dadoMySql;
}
Using the lock keyword also gives you a stronger guarantee that Monitor.Exit nearly always gets called. A good example is when an exception is thrown inside of lock scope.
I have a critical section which is to be executed only once but is invoked by many scenarios. How can I execute this thread proc and skip all the rest of the calls?
Thanks in advance.
// Assuming this uses calls from multiple threads, I used volatile.
volatile bool executed = false;
object lockExcecuted = new object();
void DoSomething()
{
lock (lockExecuted)
{
if (executed) return;
executed = true;
}
// do something
}
public static bool hasExecuted = false;
static readonly object lockObject = new object();
static void Method()
{
lock(lockObject)
{
if(!hasExecuted)
{
// run code
hasExecuted = true;
}
}
}
lock is the preferred method; unless you have more detailed requirements.
EDIT: the addition of "only once" means lock is insufficient.
Use lock to allow only one thread to access the critical section and when it's complete set a flag saying it's done.
Depends on ur scenario. If this section returns a value, u can use the new feature of .Net 4.0 - Lazy(T)
Of course, you can always just set a flag within ur critical section, and check its value before executing (which is sometimes being done when using the singleton pattern)
I noticed the following code from our foreign programmers:
private Client[] clients = new Client[0];
public CreateClients(int count)
{
lock (clients)
{
clients = new Client[count];
for(int i=0; i<count; i++)
{
Client[i] = new Client();//Stripped
}
}
}
It's not exactly proper code but I was wondering what exactly this will do. Will this lock on a new object each time this method is called?
To answer your question of "I was wondering what exactly this will do" consider what happens if two threads try to do this.
Thread 1: locks on the clients reference, which is `new Client[0]`
Thread 1 has entered the critical block
Thread 1: makes a array and assigns it to the clients reference
Thread 2: locks on the clients reference, which is the array just made in thread 1
Thread 2 has entered the critical block
You know have two threads in the critical block at the same time. That's bad.
This lock really does nothing. It locks an instance of an object which is immediately changed such that other threads entering this method will lock on a different object. The result is 2 threads executing in the middle of the lock which is probably not what was intended.
A much better approach here is to use a different, non-changing object to lock on
private readonly object clientsLock = new object();
private Client[] clients = new Client[0];
public CreateClients(int count) {
lock (clientsLock) {
clients = new string[count];
...
}
}
This code is wrong - it will lock on a new instance every time it's called.
It should look like that:
private static readonly object clientsLock = new object();
private static string[] Clients = null;
public CreateClients(int count)
{
if(clients == null)
{
lock (clientsLock)
{
if(clients == null)
{
clients = new string[count];
for(int i=0; i<count; i++)
{
client[i] = new Client();//Stripped
}
}
}
}
}
There's no point in locking every time the method is called - that's why the surrounding if clause.
Use :
private object = new Object();
lock(object){
//your code
}
I think you're correct to doubt this code!
This code will lock on the previous instance each time - this might be the desired effect, but I doubt it. It won't stop multiple threads from creating multiple arrays.
When is it appropriate to use either the Monitor class or the lock keyword for thread safety in C#?
EDIT:
It seems from the answers so far that lock is short hand for a series of calls to the Monitor class. What exactly is the lock call short-hand for? Or more explicitly,
class LockVsMonitor
{
private readonly object LockObject = new object();
public void DoThreadSafeSomethingWithLock(Action action)
{
lock (LockObject)
{
action.Invoke();
}
}
public void DoThreadSafeSomethingWithMonitor(Action action)
{
// What goes here ?
}
}
Update
Thank you all for your help : I have posted a another question as a follow up to some of the information you all provided. Since you seem to be well versed in this area, I have posted the link: What is wrong with this solution to locking and managing locked exceptions?
Eric Lippert talks about this in his blog:
Locks and exceptions do not mix
The equivalent code differs between C# 4.0 and earlier versions.
In C# 4.0 it is:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
{ body }
}
finally
{
if (lockWasTaken) Monitor.Exit(temp);
}
It relies on Monitor.Enter atomically setting the flag when the lock is taken.
And earlier it was:
var temp = obj;
Monitor.Enter(temp);
try
{
body
}
finally
{
Monitor.Exit(temp);
}
This relies on no exception being thrown between Monitor.Enter and the try. I think in debug code this condition was violated because the compiler inserted a NOP between them and thus made thread abortion between those possible.
lock is just shortcut for Monitor.Enter with try + finally and Monitor.Exit. Use lock statement whenever it is enough - if you need something like TryEnter, you will have to use Monitor.
A lock statement is equivalent to:
Monitor.Enter(object);
try
{
// Your code here...
}
finally
{
Monitor.Exit(object);
}
However, keep in mind that Monitor can also Wait() and Pulse(), which are often useful in complex multithreading situations.
Update
However in C# 4 its implemented differently:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
//your code
}
finally
{
if (lockWasTaken)
Monitor.Exit(temp);
}
Thanx to CodeInChaos for comments and links
Monitor is more flexible. My favorite use case of using monitor is:
When you don't want to wait for your turn and just skip:
//already executing? forget it, lets move on
if (Monitor.TryEnter(_lockObject))
{
try
{
//do stuff;
}
finally
{
Monitor.Exit(_lockObject);
}
}
As others have said, lock is "equivalent" to
Monitor.Enter(object);
try
{
// Your code here...
}
finally
{
Monitor.Exit(object);
}
But just out of curiosity, lock will preserve the first reference you pass to it and will not throw if you change it. I know it's not recommended to change the locked object and you don't want to do it.
But again, for the science, this works fine:
var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
tasks.Add(Task.Run(() =>
{
Thread.Sleep(250);
lock (lockObject)
{
lockObject += "x";
}
}));
Task.WaitAll(tasks.ToArray());
...And this does not:
var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
tasks.Add(Task.Run(() =>
{
Thread.Sleep(250);
Monitor.Enter(lockObject);
try
{
lockObject += "x";
}
finally
{
Monitor.Exit(lockObject);
}
}));
Task.WaitAll(tasks.ToArray());
Error:
An exception of type 'System.Threading.SynchronizationLockException'
occurred in 70783sTUDIES.exe but was not handled in user code
Additional information: Object synchronization method was called from
an unsynchronized block of code.
This is because Monitor.Exit(lockObject); will act on lockObject which has changed because strings are immutable, then you're calling it from an unsynchronized block of code.. but anyway. This is just a fun fact.
Both are the same thing. lock is c sharp keyword and use Monitor class.
http://msdn.microsoft.com/en-us/library/ms173179(v=vs.80).aspx
The lock and the basic behavior of the monitor (enter + exit) is more or less the same, but the monitor has more options that allows you more synchronization possibilities.
The lock is a shortcut, and it's the option for the basic usage.
If you need more control, the monitor is the better option. You can use the Wait, TryEnter and the Pulse, for advanced usages (like barriers, semaphores and so on).
Lock
Lock keyword ensures that one thread is executing a piece of code at one time.
lock(lockObject)
{
// Body
}
The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement and then releasing the lock
If another thread tries to enter a locked code, it will wait, block, until the object is released.
Monitor
The Monitor is a static class and belongs to the System.Threading namespace.
It provides exclusive lock on the object so that only one thread can enter into the critical section at any given point of time.
Difference between Monitor and lock in C#
The lock is the shortcut for Monitor.Enter with try and finally.
Lock handles try and finally block internally
Lock = Monitor + try finally.
If you want more control to implement advanced multithreading solutions using TryEnter() Wait(), Pulse(), and PulseAll() methods, then the Monitor class is your option.
C# Monitor.wait(): A thread wait for other threads to notify.
Monitor.pulse(): A thread notify to another thread.
Monitor.pulseAll(): A thread notifies all other threads within a process
In addition to all above explanations, lock is a C# statement whereas Monitor is a class of .NET located in System.Threading namespace.
Okay. I want to have two threads running. Current code:
public void foo()
{
lock(this)
{
while (stopThreads == false)
{
foreach (var acc in myList)
{
// process some stuff
}
}
}
}
public void bar()
{
lock(this)
{
while (stopThreads == false)
{
foreach (var acc in myList)
{
// process some stuff
}
}
}
}
Both are accessing the same List, the problem is that the first thread "foo" is not releasing the lock i guess; because "bar" only starts when "foo" is done. Thanks
Yes, that's how lock is designed to work.
The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock.
Mutual-exclusion means that there can be at most one thread that holds the lock at any time.
Locking on this is a bad idea and is discouraged. You should create a private object and lock on that instead. To solve your problem you could lock on two different objects.
private object lockObject1 = new object();
private object lockObject2 = new object();
public void foo()
{
lock (lockObject1)
{
// ...
}
}
public void bar()
{
lock (lockObject2)
{
// ...
}
}
Alternatively you could reuse the same lock but move it inside the loop so that each loop has a chance to proceed:
while (stopThreads == false)
{
foreach (var acc in myList)
{
lock (lockObject)
{
// process some stuff
}
}
}
However I would suggest that you spend some time to understand what is going on rather than reordering the lines of code until it appears to work on your machine. Writing correct multithreaded code is difficult.
For stopping a thread I would recommend this article:
Shutting Down Worker Threads Gracefully
Since you are not really asking a question, I suggest you should read a tutorial on how threading works. A .Net specific guide can be found here. It features the topics "Getting Started", "Basic Synchronization", "Using Threads", "Advanced Threading" and "Parallel Programming".
Also, you are locking on "this". The Msdn says:
In general, avoid locking on a public
type, or instances beyond your code's
control. The common constructs lock
(this), lock (typeof (MyType)), and
lock ("myLock") violate this
guideline:
lock (this) is a problem if the
instance can be accessed publicly.
lock (typeof (MyType)) is a problem if
MyType is publicly accessible.
lock(“myLock”) is a problem because
any other code in the process using
the same string, will share the same
lock.
Best practice is to define a private
object to lock on, or a private static
object variable to protect data common
to all instances.
The problem you have is that you work with a very coarse lock. Both Foo and Bad basically do not work concurrently because whoever starts first stops the other one for the COMPLETE WORK CYCLE.
It should, though, ONLY lock WHILE IT TAKES THINGS OUT OF THE LIST. Foreach does not work here - per definition. You ahve to put up a second list and have each thread REMOVE THE TOP ITEM (while lockin), then work on it.
Basically:
Foreach does not work, as both threads will run through the compelte list
Second, locks must be granular in that they only lock while needed.
In your case, you lock in foo will only be released when foo is finished.