开发者

Java-like thread synchronization in C#

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:

pri开发者_运维技巧vate 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.


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;
  }
}


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;
}


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.


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;
    }
}


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.
   }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜