C#中类似Java的线程同步

时间:2009-10-26 15:03:07

标签: c# java multithreading thread-safety

我是一名Java程序员,我知道一些关于线程化Java的事情。

在Java中,我可以使用synchronized关键字锁定方法:

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

我在msdn中搜索过,看到c#中有一些玩具可以玩线程。例如monitor.Enter,monitor.Exit,lock或高级的互斥锁。

但我需要的是同步一种方法。在c#中它的等价物是什么?

提前致谢。

5 个答案:

答案 0 :(得分:6)

在C#中没有直接的等价物,但你可以用这个做同样的事情:

private readonly object changeVarsLockObject = new object();

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

答案 1 :(得分:4)

这样的事可能是:

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

答案 2 :(得分:4)

直接相当于使用lock(this):

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

或者确实使用了R. Bemrose所描述的MethodImplAttribute,这相当于:

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

...但是,不建议使用公开可见的对象进行锁定,因为其他人也可能决定将其用作锁定对象,因此更好的翻译将是:

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

答案 3 :(得分:4)

为了清楚 - 声明在Java中同步的方法要求调用者将监视器保存在调用该方法的对象上(这是静态方法的Class对象)。

所以说你可以“锁定一个方法”是误导性的,因为你没有完全锁定那个方法(仍然可以在不同的实例对象上调用相同的方法),并且你锁定更多方法(不需要目标对象监视器的其他代码,包括其他同步方法或显式获取它,可以同时运行)。

同步很难,理想情况下,如果您想避免在测试期间几乎不会出现的死锁和可见性问题,或者有助于调试,那么您需要了解更多关于它的“事情”。 。对一种语言中的同步进行可能不完全的理解,并尝试将其转换为具有不同原语的另一种语言,并且可能是不同的内存模型,这是一种灾难。

因此,虽然这不是您所寻求的一线答案,但我会断言任何一线答案注定会在没有整个生态系统知识的情况下失败来支持它。因此,您应该阅读有关C#同步的好书/教程,而不是尝试按关键字翻译您的Java体验关键字。

答案 4 :(得分:3)

首选解决方案是将方法体包装在lock语句中。

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

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

您也可以使用声明性同步,但这有一个明显的缺点,即您必须从ContextBoundObject派生,并且所有使用Synchronization属性修饰的方法共享限制锁粒度的相同锁定对象。

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