【问题标题】:Lock on an class member vs having that object initialized in class' method?锁定类成员与在类方法中初始化该对象?
【发布时间】:2019-12-12 15:57:00
【问题描述】:

所以,我有这个服务,我们称之为“MyService”。 MyService 有一个公共方法,即“executeBatchJob”,顾名思义,它将执行一个批处理作业,简而言之,从数据库中检索一些数据,在某些时候,我有一个非常像实体的对象,具有一个 ID 和一个记录列表。在我的方法executeBatchJob中,进行了一些检查,当满足某些条件时,实体被写入某处并重新初始化(新ID,不同的记录),但请注意它发生在executeBatchJob调用的私有方法中。在其他情况下,在不同的私有方法中,记录被添加到实体持有的记录列表中。

我的问题是:由于服务可能被多个进程调用:将该实体声明为类成员(私有只读)并在需要时将其锁定,然后使用一种方法来清除实体的状态是否更好为下一个过程。还是在我的方法executeBatchJob中声明和使用这个对象更好,但是通过所有私有方法拖动对象,因为对象的状态可以在几个“级别”上改变?

为了说明我在解释什么:

这是我的实体:

public class MyEntity
{
 public int Id { get; set; }
 public List<Record> Records { get;  set; }

 public void CleanUp(int newId)
 {
     Id = newId;
     Records.Clear();
 }
}

这是带锁的 myService :

public class MyService : IMyService
{
 private readonly MyEntity _myEntity;

 public MyService()
 {
     _myEntity = new MyEntity();
 }

 public void executeBatchJob(int batchId)
 {
     //some code
     lock(_myEntity)
     {
        // More code and call to some private method
        _myEntity.CleanUp();
     }

     // still more code
 }
}

或者使用第二个选项:

public class MyService : IMyService
{

 public MyService()
 {
 }

 public void executeBatchJob(int batchId)
 {
     MyEntity myEntity = new MyEntity();

     APrivateMethodInExecuteBatchJob(myEntity);
     // more code

 }

 private returnResult APrivateMethodInExecuteBatchJob(MyEntity myEntity)
 {
      // Some manipulation of myEntity
      // some code, with another call to a private method with myEntity, and manipulation of myEntity

      // ... write the entity
      myRepository.write(myEntity);

 }
}

为了提供更多上下文,据我所知,每次写入实体时,都必须对其进行清理,在第二个选项中,我可以只执行“new MyEntity()”(这更有意义从商业角度)。

对我来说,第二个解决方案更合乎逻辑且更合适,但是,我将有几个私有方法来移动对象,有时只是将它传递给另一个私有方法,而不需要任何其他操作,而不是“传递”给那个其他私有方法...根本不干净...

这就是为什么我需要您的建议/意见。

【问题讨论】:

    标签: c# .net-core synchronization


    【解决方案1】:

    使用IDisposable接口,它的用途正是你在做的事情

    public class MyEntity: IDisposable;
    

    然后您可以使用 using 关键字使用第二个选项。

    您可以在此处查看有关实施内容和实施方式的示例。 https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

    示例代码:

    public void executeBatchJob(int batchId)
    {
    
        using (vMyEntity myEntity = new MyEntity();) 
        {
           APrivateMethodInExecuteBatchJob(myEntity);
           // more code
        }
    
    }
    

    一般来说,尽量避免在不需要时使用锁。它可能会产生竞争条件,从而降低您的应用程序的响应速度。

    【讨论】:

    • 谢谢,我还是 C sharp 和 .Net 的新手,我忘记了 IDisposable 关键字,即使我最近使用过它。
    【解决方案2】:

    如果实体不应该保持其状态,那么在我看来,具有选项 2 中的幂等方法要好得多。如果您可以将方法设为静态,您最终会得到一个更简单的架构。

    正如您已经确定的那样,您将遇到需要在选项 1 中锁定资源的问题,并且只要在清理过程中丢弃了状态,那么这种头痛是没有意义的。

    我能看到类似于选项 1 的唯一原因是,如果实体是由未在使用之间清除的交易建立的,或者实体由于某种原因创建起来非常昂贵。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-02
      • 2018-01-17
      • 2015-03-22
      • 2017-08-16
      • 2014-10-13
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多