views:

322

answers:

5

Hello,

I am a Java programmer and I know a few things about threading int Java.

In Java I can lock a method by using synchronized keyword:

private int a;
private int b;
private int c;
private synchronized void changeVars()
{
  a = 4;
  b = 2;
  c = a+b;
}

I searched in msdn and saw that there are a few toys in c# to play with threads. Such as monitor.Enter, monitor.Exit, lock or an advanced one mutex.

But what I need is to synchronize one method. What is the equivalent of it in c#?

Thanks in advance.

+3  A: 

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;
}
R. Bemrose
I probably should have mentioned in the body that I modified this answer shortly after posting it; I thought that MethodImpl was a better choice than lock(this) because it lets the compiler choose the best method.
R. Bemrose
It's probably worth mentioning that both MethodImplOption.Synchronized and lock(this) are no longer advised as ways of writing thread safe methods because of the deadlock opportunities they create. The following blog has more details: http://blogs.msdn.com/bclteam/archive/2004/01/20/60719.aspx
LBushkin
+3  A: 

The preferred solution is to wrap the method body in a lock statement.

internal class Foo
{
   private Object lockObject = new Object();

   private void ChangeVars()
   {
      lock (this.lockObject)
      {
         // Manipulate the state.
      }
   }
}

You can use declarative synchronization, too, but this has the obvious drawback that you have to derive from ContextBoundObject and all methods decorated with the Synchronization attribute share the same lock object limiting the lock granularity.

internal class Foo : ContextBoundObject
{
   [Synchronization]
   private void ChangeVars()
   {
      // Manipulate the state.
   }
}
Daniel Brückner
+6  A: 

There's no direct equivalent in C#, but you can do the same thing with this:

private readonly object changeVarsLockObject = new object();

private void changeVars()
{
  lock(changeVarsLockObject)
  {
    a = 4;
    b = 2;
    c = a+b;
  }
}
FacticiusVir
There is a direct translation to C# ...
Freed
Not in the language; I might be better to say that there's no equivalent keyword in C#, but you can write code to do the same thing.
FacticiusVir
+4  A: 

The direct equivalent of that is using lock (this):

private void ChangeVars()
{
    lock (this) {
        a = 4;
        b = 2;
        c = a+b;
    }
}

or indeed using the MethodImplAttribute as described by R. Bemrose, which amounts to the same thing:

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

... however, it is not recommended to use a publically visible object for locking, since someone else might decide to use it as a lock object as well, so a better translation would be:

private object monitor = new object();
private void ChangeVars()
{
    lock (monitor) {
        a = 4;
        b = 2;
        c = a+b;
    }
}
Freed
+4  A: 

Just to be clear - declaring a method synchronized in Java requires that the caller holds the monitor on the object that the method was called on (which is the Class object for static methods).

So saying you can "lock a method" is misleading as you don't wholly lock that method (the same method can still be called on different instance objects), and you lock more than that method (no other bit of code that requires the target object's monitor, including other synchronized methods or explicit acquires of it, can run at the same time).

Synchronization is hard, and ideally you need to know more than "a few things" about it if you want to avoid deadlocks and visibility issues that almost never appear during testing, or are conducive to debugging. Taking a possibly incomplete understanding of synchronization in one language, and trying to carry it over to another language with different primitives and likely a different memory model is a recipe for disaster.

So while this isn't the one-liner answer you were looking for, I'm going to assert that any one-liner answer is doomed to fail without the knowledge of the whole ecosystem to back it up. Thus you should read a good book/tutorial on synchronization in C#, rather than trying to translate your Java experience keyword by keyword.

Andrzej Doyle
"Thus you should read a good book/tutorial on synchronization in C#, rather than trying to translate your Java experience keyword by keyword." Wait, are you seriously implying that this somehow isn't an issue in Java as well?
R. Bemrose
+1 Did not know that about the synchronized keyword. Is it possible to take equivalent locks from outside the object?
FacticiusVir
@FacticiusVir, you can use synchronized (instance) to take the same lock as would be taken by Java when entering a method declared as synchronized on that instance (or explicitly use the Monitor methods).
Freed
@Freed No, the C#/.NET code I get, as I do a lot of work with .NET synchronisation structures; it's the Java code that I'm unfamiliar with. And that's why I asked the question; if there is no method in Java that is equivalent to lock(instance) in C#, then there are important differences between "synchronized" in Java and "lock(this)" in C#.
FacticiusVir
@FacticiusVir, the synchronized keyword can be used at block level in Java, just like the lock keyword in C#, and synchronized on a method does use the object instance, or the Class instance if used on a static method. Nothing in this answer contradicts that, dtsazza simply points out that it's not the _method_ that is being locked.
Freed
@Freed Ah, I see. I'd misunderstood your comment. Thanks!
FacticiusVir
@R. Bemrose - no, not at all, that was simply my answer to the question. I don't want to *assume* that the OP doesn't fully get synchronization in Java, though of course if he feels his knowledge is at all lacking it would be a good thing to improve it.
Andrzej Doyle