C# version of java's synchronized keyword?
Does c# have its own version of the java "synchronized" keyword?
I.e. in java it can be specified either to a function, an object or a block of code, like so:
public synchronized void doImportantStuff() {
// dangerous code goes here.
}
or
public void doImportantStuff() {
// trivial stuff
synchronized(someLock) {
// dangerous code goes here.
}
}
Solution 1:
First - most classes will never need to be thread-safe. Use YAGNI: only apply thread-safety when you know you actually are going to use it (and test it).
For the method-level stuff, there is [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
This can also be used on accessors (properties and events):
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Note that field-like events are synchronized by default, while auto-implemented properties are not:
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Personally, I don't like the implementation of MethodImpl
as it locks this
or typeof(Foo)
- which is against best practice. The preferred option is to use your own locks:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Note that for field-like events, the locking implementation is dependent on the compiler; in older Microsoft compilers it is a lock(this)
/ lock(Type)
- however, in more recent compilers it uses Interlocked
updates - so thread-safe without the nasty parts.
This allows more granular usage, and allows use of Monitor.Wait
/Monitor.Pulse
etc to communicate between threads.
A related blog entry (later revisited).
Solution 2:
static object Lock = new object();
lock (Lock)
{
// do stuff
}
Solution 3:
Does c# have its own version of the java "synchronized" keyword?
No. In C#, you explicitly lock
resources that you want to work on synchronously across asynchronous threads. lock
opens a block; it doesn't work on method level.
However, the underlying mechanism is similar since lock
works by invoking Monitor.Enter
(and subsequently Monitor.Exit
) on the runtime. Java works the same way, according to the Sun documentation.
Solution 4:
Take note, with full paths the line: [MethodImpl(MethodImplOptions.Synchronized)]
should look like
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]