本文介绍了C#中的引用锁定传递给方法 - 不好的做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法类似:

 公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject O)
{
   // .....

   锁定(O)
   {
       o.Things.Add(参数1);
       o.Update();
       // 等等....
   }
}
 

的几点:

  1. 是锁定在这样不好的做法?
  2. 我应该锁定在私有静态对象呢?
  3. 如果是这样,为什么
解决方案

要最大限度地减少副作用,该对象被锁定在不应该的对象被操纵,而是一个独立的对象指定为锁定。

根据您的要求,有几个选项来处理这个问题:

方案A:私人锁定对象

选择这个,如果你只是想确保的DoSomething 不与 DoSomething的一个平行的实例冲突

 私有静态只读对象doSomethingLock =新的对象();

公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject O)
{
   // .....

   锁定(doSomethingLock)
   {
       o.Things.Add(参数1);
       o.Update();
       // 等等....
   }
}
 

方案B:通过锁定对象作为参数

如果

选择此访问 0 必须是线程安全的外连的DoSomething ,即,如果可能存在别人写了一个方法 DoSomethingElse 它运行在平行于的DoSomething 并不得与<$ C干扰

:$ C>锁定在的DoSomething

 公共静态无效DoSomething的(字符串参数1,字符串参数2,SomeObject 0,对象someObjectLock)
{
   // .....

   锁定(someObjectLock)
   {
       o.Things.Add(参数1);
       o.Update();
       // 等等....
   }
}
 

变通方案C:创建SyncRoot属性

如果你有超过 SomeObject 的实施控制,这可能是方便的为客户提供锁定对象的属性。通过这种方式,可以实现变式B,而不必绕过第二个参数:

 类SomeObject
{
    私人只读对象SyncRoot上=新的对象();

    公共对象SyncRoot上{{返回SyncRoot上; }}

    ...
}
 

然后,你只需要使用锁(o.SyncRoot)的DoSomething 。这是一些BCL类使用模式,例如, Array.SyncLock , ICollection.SyncRoot.

I have a method similar to:

public static void DoSomething (string param1, string param2, SomeObject o) 
{
   //.....

   lock(o) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

A few points:

  1. Is locking in this way bad practice?
  2. Should I lock on a private static object instead?
  3. If so, why?
解决方案

To minimize side effects, the object being locked on should not be the object being manipulated but rather a separate object designated for locking.

Depending on your requirements, there are a few options for handling this issue:

Variant A: Private locking object

Choose this if you just want to ensure that DoSomething does not conflict with a parallel instance of DoSomething.

private static readonly object doSomethingLock = new object();

public static void DoSomething (string param1, string param2, SomeObject o) 
{
   //.....

   lock(doSomethingLock) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

Variant B: Pass locking object as a parameter

Choose this if access to o must be thread-safe even outside of DoSomething, i.e., if the possibility exists that someone else writes a method DoSomethingElse which runs in parallel to DoSomething and which must not interfere with the lock block in DoSomething:

public static void DoSomething (string param1, string param2, SomeObject o, object someObjectLock) 
{
   //.....

   lock(someObjectLock) 
   {
       o.Things.Add(param1);
       o.Update();
       // etc....
   }
}

Variant C: Create SyncRoot property

If you have control over the implementation of SomeObject, it might be convenient to provide the locking object as a property. That way, you can implement Variant B without having to pass around a second parameter:

class SomeObject
{
    private readonly object syncRoot = new object();

    public object SyncRoot { get { return syncRoot; } }

    ...
}

Then, you just use lock(o.SyncRoot) in DoSomething. That's the pattern some of the BCL classes use, e.g., Array.SyncLock, ICollection.SyncRoot.

这篇关于C#中的引用锁定传递给方法 - 不好的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 18:04