C# Version of Java's Synchronized Keyword

C# version of java's synchronized keyword?

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).

Synchronized methods in C#

Try this:

using System.Runtime.CompilerServices;
using System.Threading;

public class MessageBuffer
{
// Shared resources up here

public MessageBuffer()
{
// Initiating the shared resources
}

[MethodImpl(MethodImplOptions.Synchronized)]
public virtual void post(object obj)
{
// Do stuff
Monitor.Wait(this);
// Do more stuff
Monitor.PulseAll(this);
// Do even more stuff
}

[MethodImpl(MethodImplOptions.Synchronized)]
public virtual object fetch()
{
// Do stuff
Monitor.Wait(this);
// Do more stuff
Monitor.PulseAll(this);
// Do even more stuff and return the object
}
}

Couple of questions regarding the synchronized keyword in Java (and C#'s lock)

1 Are the following classes equivalent in Java? if no, why?

They differ by what instance they synchronize on and thus are affected by the differences between those instances.

Class Abc uses the Abc instance that the method is being invoked upon. Other code with access to the instance can use it to synchronize as well by explicitly using the instance in a synchronized block.

The synchronize code blocks in Class Def explicitly name the instance they synchronizes with. Since this instance is private to the Def instance, code external to Def cannot use it to synchronize (unless the instance is somehow leaked).

Some may argue that the Def approach is much safer, that it is important to encapsulate your locks for the same reason you should use private instance variables.

Finally, there are the differences between the synchronized keyword and using the synchronized statement, e.g. the synchronized statement can lock on any object, not just the instance of the executing code, the synchronize keyword is slightly more efficient, etc.

2a Also, what would be the problem of in Def, using this as synchronized parameter instead of lock?

No problem. Using synchronized keyword on an instance method is semantically identical to wrapping the code of the method in a synchronized block synchronized on this (the synchronized keyword is slightly more efficient). Using the synchronized keyword on a static method is the same as using a synchronized block synchronized on the class itself (e.g. synchronized(FooBar.class) { ... }).

2b Is the following the problem?

No, locks in Java are reentrant, which just means that the thread holding the lock on the protecting instance can enter and exit any other code block synchronized on the same instance.

3a Are synchronized statements in Java just like C#'s lock statements? If no, what are their differences?

Semantically equivalent.

http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized#Synchronized_code_blocks

But note this answer about Monitor.Enter and Monitor.Exit

Are there any differences between Java's "synchronized" and C#'s "lock"?

3b If yes, why doesn't C# also allow to lock the methods, like Java allows?

It does - use the [MethodImpl(MethodImplOptions.Synchronized)] annotation.

http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized#Synchronized_methods

4 Thread1 calls xyz.add(0) and at the same time Thread2 tries to call xyz.show666(). Thread2 has to wait for Thread1 to finish with xyz.add(0) althtough it doesn't need any info directly related with the lock. Is that it?

No, a lot of people assume "locking" an instance affects the entire instance. It only affects synchronized code (synchronized methods and code within a synchronized statement) that is synchronized on that instance. Unsynchronized code is unaffected (at least until it hits a synchronized statement or calls a synchronized method).

The unsynchronized method show666() won't cause the thread to block. Nothing changes if the synchronized(this) statements were changed into synchronized methods - again show666 won't block (unless its synchronized too).

Are there any differences between Java's synchronized and C#'s lock?

According to this site: http://en.csharp-online.net/CSharp_FAQ:_What_is_the_difference_between_CSharp_lock_and_Java_synchronized, C# lock and Java synchronized code blocks are "semantically identical", while for methods, Java uses synchronized while C# uses an attribute: [MethodImpl(MethodImplOptions.Synchronized)].

What is the equivelent of the synchronize block in Java, in C# ASP.NET?

You could use the lock statement or decorate a method with the [MethodImpl(MethodImplOptions.Synchronized)] attribute to allow access to this block/method only from a single thread at a time.

Java-like thread synchronization in C#

Something like this mayhaps:

using System.Runtime.CompilerServices;

...

private int a;
private int b;
private int c;

[MethodImpl(MethodImplOptions.Synchronized)]
private void changeVars()
{
a = 4;
b = 2;
c = a+b;
}


Related Topics



Leave a reply



Submit