Synchronizing Java Streams in C #

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

In Java, I can block a method using a 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 several toys in C # to play with threads. For example, monitor.Enter, monitor.Exit, lock, or extended mutex.

But I need to sync one method. What's the equivalent to it in C #?

Thanks in advance.

+2


source to share


5 answers


Something like this is possible:



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

      

+4


source


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



private readonly object changeVarsLockObject = new object();

private void changeVars()
{
  lock(changeVarsLockObject)
  {
    a = 4;
    b = 2;
    c = a+b;
  }
}

      

+6


source


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

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

      

or indeed using 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 publicly visible object for a lock, as 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;
    }
}

      

+4


source


Just to be clear - declaring a method synchronized in Java requires the caller to contain a monitor on the object that the method was called on (which is an object Class

for static methods).

So to say that you can "block a method" is misleading because you do not completely block this method (the same method can still be called on different instance objects), and you block more than this method (no other bit of code that requires that the target monitor, including other synchronized methods or explicit acquisitions, can run concurrently).

Synchronization is tough , 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 show up during testing, or facilitate debugging. Assuming a possibly incomplete understanding of synchronization in one language, and trying to port it to another language with different primitives and probably a different memory model is a recipe for disaster.

So, while this is not the answer to the one liner you were looking for, I will argue that any answer to one liner is doomed to fail without knowing the entire ecosystem to support it. So you should read a good book / tutorial on Synchronization in C # and not try to translate the Java keyword by keyword.

+4


source


The preferred solution is to wrap the method body in an expression lock

.

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

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

      

You can also use declarative synchronization, but this has an obvious drawback that you have to get from ContextBoundObject

and all methods decorated with the attribute Synchronization

use the same lock object limiting the granularity of the lock.

internal class Foo : ContextBoundObject
{
   [Synchronization]
   private void ChangeVars()
   {
      // Manipulate the state.
   }
}

      

+3


source







All Articles