从多个线程访问Singleton实例中的方法

时间:2015-12-29 18:46:42

标签: c# multithreading singleton ninject

我使用Ninject作为我的IOC。我有两个课程,如下所示。

客户:

public class Customer:ICustomer
{
   private ICustomerRepository _CustRepo;
   public Customer(ICustomerRepository custRepo){
     _CustRepo = custRepo;
   }

   public void CustomerOperations(int custId){

     var cust = _CustRepo.GetCustomer(custId);

     //Do something with the cust object     

     if(condition1)
      _CustRepo.Update(cust);
     if(condition2)
      _CustRepo.Delete(cust.id);
     if(condition3)
      _CustRepo.Insert(cust);
   }
}

存储库:

public class CustomerRepository:ICustomerRepository {

   private IDataAccessLayer _Dal;

   //Ctor details skipped

   public Customer GetCustomer(int custId) {//Get customer from DB}
   public bool Update(Customer c) {//Update}
   public bool Delete(int custID) {//Delete}
   public bool Insert(Customer c) {//Insert}
}

绑定:

     Bind<ICustomer>().To<Customer>().InThreadScope();
     Bind<ICustomerRepository>().To<CustomerRepository>().InSingletonScope();

我们假设范围无法改变。我正在尝试同步调用,因此当thread2准备更新同一客户时,thread1不会删除客户。

如果建议使用锁定,我如何确保存储库方法是线程安全的。谢谢

2 个答案:

答案 0 :(得分:0)

这是锁定无法解决的并发问题。

请考虑以下事项: 客户端A在客户端B可以进行删除之前请求删除客户。在这种情况下会发生以下情况:

  1. 客户A获取客户/存储库上的锁
  2. 客户端B请求锁定,但必须等到客户端A发布锁定
  3. 客户A成功删除客户
  4. 客户A释放锁
  5. 客户B获取锁
  6. 客户B更新客户的请求失败,因为客户已被删除。
  7. 查看基础数据存储的concurrency control机制。

    如果您使用的是SQL Server + EF,请查看此article

答案 1 :(得分:0)

正如MattTannahill所说,这是一个并发问题。

实现您想要完成的任务的唯一方法是推迟执行不返回的实际点(更新/删除),并在此之前进行正确的簿记,以提供足够的信息来执行正确的序列或操作序列......由于缺乏更好的解释,您将从记录操作方程中删除并发。

所以基本上,你有一个与记录相关联的“事务日志/跟踪”,并且记录的实际操作直到稍后安全才会发生。与此同时,记录以“待更新”状态存储。

当然,这会打开你需要解决的其他事情,而且很快就会无法管理:

  • 如何显示尚未执行操作的更新/删除记录。

  • 最终说什么交易?你在这里暗示的是更新应该取消并发删除。如果您等待执行所有操作并分析事务跟踪,则可以执行此操作。这种事情的规则随着时间的推移会变得非常复杂,因为你必须从客户端交互的角度来“标记操作的记录”,然后是一个过程作业,以便以后实际分析和执行操作。 / p>

  • 如果更新“取消”删除,由于操作稍后进行,因此没有立即让用户知道它没有删除的方法。你必须想办法让这个用户知道。

  • 您需要定义执行这些修改的“安全”时间。你没有记录活动30秒后这样做吗?是否存在始终优先的某些修改?