锁定 class 成员与在 class 方法中初始化该对象?
Lock on an class member vs having that object initialized in class' method?
所以,我有这项服务,我们称它为"MyService"。 MyService 有一个 public 方法,就是 "executeBatchJob",顾名思义,它会执行一个 batchJob,简而言之,从数据库中检索一些数据,在某些时候,我有一个对象非常很像一个实体,有一个 ID 和一个记录列表。在我的方法 executeBatchJob 中,进行了一些检查,当满足某些条件时,将实体写入某处并重新初始化(新 ID,不同的记录),但请注意,它发生在 executeBatchJob 调用的私有方法中。在其他情况下,在不同的私有方法中,记录被添加到实体持有的记录列表中。
我的问题是:由于该服务可能会被多个进程调用:将该实体声明为 class 成员(私有只读)并在需要时锁定它,然后使用一个方法是否更好?这将为下一个过程清除实体的状态。还是在我的方法 executeBatchJob 中声明和使用此对象更好,但是通过所有私有方法拖动对象,因为对象的状态可以在几个 "level" 时改变?
为了向您说明我在解释什么:
这是我的实体:
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()"(这使得更多从商业角度来看。
对我来说,第二个解决方案更合乎逻辑,也更合适,但是,我将有几个私有方法来移动对象,有时只是将它传递给另一个私有方法,而不需要任何其他操作 "passing" 它到另一个私有方法...根本不干净...
这就是为什么我需要你的建议/意见。
使用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
}
}
一般来说,尽量避免在不需要的时候使用锁。它可能会产生竞争条件,从而降低您的应用程序的响应速度。
如果实体不应该保持它的状态,在我看来,它比选项 2 中的幂等方法要好得多。如果你可以使方法静态,你最终会得到一个更简单的体系结构。
正如您所确定的那样,您将遇到需要在选项 1 中锁定资源的问题,只要在清理期间丢弃状态,就没有必要为此头疼。
我能看到选项 1 之类的唯一原因是,如果实体是由在使用之间未清除的事务构建的,或者实体是否出于某种原因创建起来非常昂贵。
所以,我有这项服务,我们称它为"MyService"。 MyService 有一个 public 方法,就是 "executeBatchJob",顾名思义,它会执行一个 batchJob,简而言之,从数据库中检索一些数据,在某些时候,我有一个对象非常很像一个实体,有一个 ID 和一个记录列表。在我的方法 executeBatchJob 中,进行了一些检查,当满足某些条件时,将实体写入某处并重新初始化(新 ID,不同的记录),但请注意,它发生在 executeBatchJob 调用的私有方法中。在其他情况下,在不同的私有方法中,记录被添加到实体持有的记录列表中。
我的问题是:由于该服务可能会被多个进程调用:将该实体声明为 class 成员(私有只读)并在需要时锁定它,然后使用一个方法是否更好?这将为下一个过程清除实体的状态。还是在我的方法 executeBatchJob 中声明和使用此对象更好,但是通过所有私有方法拖动对象,因为对象的状态可以在几个 "level" 时改变?
为了向您说明我在解释什么:
这是我的实体:
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()"(这使得更多从商业角度来看。
对我来说,第二个解决方案更合乎逻辑,也更合适,但是,我将有几个私有方法来移动对象,有时只是将它传递给另一个私有方法,而不需要任何其他操作 "passing" 它到另一个私有方法...根本不干净...
这就是为什么我需要你的建议/意见。
使用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
}
}
一般来说,尽量避免在不需要的时候使用锁。它可能会产生竞争条件,从而降低您的应用程序的响应速度。
如果实体不应该保持它的状态,在我看来,它比选项 2 中的幂等方法要好得多。如果你可以使方法静态,你最终会得到一个更简单的体系结构。
正如您所确定的那样,您将遇到需要在选项 1 中锁定资源的问题,只要在清理期间丢弃状态,就没有必要为此头疼。
我能看到选项 1 之类的唯一原因是,如果实体是由在使用之间未清除的事务构建的,或者实体是否出于某种原因创建起来非常昂贵。