C#版的java的synchronized关键字?

Sor*_*raz 303 c# java multithreading synchronization

c#是否有自己的java"synchronized"关键字版本?

即在java中,它可以指定为函数,对象或代码块,如下所示:

public synchronized void doImportantStuff() {
   // dangerous code goes here.
}
Run Code Online (Sandbox Code Playgroud)

要么

public void doImportantStuff() {
   // trivial stuff

   synchronized(someLock) {
      // dangerous code goes here.
   }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 453

首先 - 大多数类永远不需要是线程安全的.使用YAGNI:只有当您知道实际要使用它时才应用线程安全(并测试它).

对于方法级别的东西,有[MethodImpl]:

[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Run Code Online (Sandbox Code Playgroud)

这也可用于访问器(属性和事件):

private int i;
public int SomeProperty
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    get { return i; }
    [MethodImpl(MethodImplOptions.Synchronized)]
    set { i = value; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,默认情况下,类似字段的事件同步的,而自动实现的属性不是:

public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Run Code Online (Sandbox Code Playgroud)

就个人而言,我不喜欢MethodImpl锁定thistypeof(Foo)- 这是违反最佳做法的实施.首选方法是使用自己的锁:

private readonly object syncLock = new object();
public void SomeMethod() {
    lock(syncLock) { /* code */ }
}
Run Code Online (Sandbox Code Playgroud)

请注意,对于类似字段的事件,锁定实现依赖于编译器; 在较旧的Microsoft编译器中它是lock(this)/ lock(Type)- 但是,在最近的编译器中它使用Interlocked更新 - 所以线程安全没有讨厌的部分.

这允许更细粒度的使用,并允许使用Monitor.Wait/ Monitor.Pulseetc在线程之间进行通信.

相关博客条目(稍后重访).

  • Marc的[链接博客文章](http://marcgravell.blogspot.com/2009/02/fun-with-field-like-events.html)有一个[2010年3月的后续行动](http://marcgravell.blogspot .com/2010/03/revisited-fun-with-field-like-events.html)说在.NET 4.0中,`MethodImpl`和类似字段的事件现在可以生成良好的同步代码,并且不再需要使用它你自己的锁. (6认同)
  • 我想我应该简单说明一下; "大多数类永远不需要是线程安全的",但"所有开发人员必须意识到并发".回想起来,我同意这个数字非常小(绝对是你想要在一个地方找到一次的东西,允许大多数类无法与他们的多线程环境进行交互).希望我快速删除评论=) (4认同)
  • 如今,大多数应用程序都是基于Web的,并具有依赖于大量实例重用和通过依赖注入的复杂对象生命周期的框架。这些天的默认思维定势倾向于错误的线程安全性。 (2认同)

Jan*_*ann 54

static object Lock = new object();

lock (Lock) 
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我们在提问者的问题的背景下,那么我们正在讨论实例方法.使用静态意味着如果线程1调用instance1.DoSomething()而线程2调用instance2.DoSomething,则第二个调用将阻塞,即使它是一个完全不同的对象.thread2的调用不应该阻止,除非有人在同一个对象上调用DoSomething**.不是说你错了,但是说在这里理解使用静态的效果很重要,因为它可能通过全局阻塞而不是基于每个实例来导致性能不佳. (31认同)
  • 当然,所以每个Thread都可以轻松访问它而不需要传递引用. (21认同)
  • 您确定要将锁定对象声明为静态..? (9认同)
  • @AaronLS 当您的对象在比自身更大的范围内执行操作时,静态锁非常有用。例如,网络服务总是会发生这种情况。 (2认同)
  • -1,因为这是与OP要求的不同的行为.这是类锁,而不是实例锁. (2认同)

Kon*_*lph 39

c#是否有自己的java"synchronized"关键字版本?

在C#中,您明确地lock要跨异步线程同步处理资源.lock打开一个街区; 它不适用于方法级别.

但是,底层机制类似,因为lock通过调用Monitor.Enter(和随后Monitor.Exit)运行时来工作.根据Sun文档,Java的工作方式相同.

  • 它没有等效的"关键字",但正如Marc Gravell上面的答案所示,您可以使用[MethodImpl(MethodImplOptions.Synchronized)]注释在方法级别进行同步. (3认同)
  • @SriHarshaChilakapati 只是部分正确,java 在方法上的`synchronized` 关键字更像是:`synchronized(this)`,只有在静态方法上它的行为才像`synchronized(class)`。 (2认同)

Tra*_*chs 7

注意,完整路径线:[MethodImpl(MethodImplOptions.Synchronized)]应该看起来像

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]

  • 或者你可以只使用`using System.Runtime.CompilerServices;` (2认同)

Jam*_*mes 5

您可以改用该lock语句.我认为这只能取代第二个版本.此外,请记住,这两个synchronizedlock需要一个对象进行操作.