首页 > 解决方案 > 当“真相源”具有通用多个操作时如何同步访问

问题描述

我有一个项目存储库,用于视图模型(主线程)和后台服务(后台线程)。两者都可以查询项目存储库和更新项目。

class ItemRepository
{
   Item GetItem(int id);

   void UpdateItem(Item item);
}

public class Item
{
    ItemState State { get; set; }
}

// Component A (view-model)
// Runs on main thread     
void ExecuteUpdateItemCommand()
{
   var item = _itemRepo.GetItem(1);
   if(item.State == ItemState.First)
   {
       itemState.State = ItemState.Second;
      _itemRepo.UpdateItem(item); // Ideally this should be on a separate thread but for now lets' assume it's on main thread
   }
}

// Component B (background service - receives notifications from backedn) 
// Runs on a background thread
void OnNotificationReceived()
{
   var item = _itemRepo.GetItem(1);
   if(item.State == ItemState.First)
   {
       item.State = GetNextState(); // some busines logic specific to Component B
       _itemRepo.UpdateItem(item);
    }
}

我遇到的问题是在两个线程之间实现项目查询和更新的同步。

如果没有同步,item 的状态可能会损坏,因为 if 语句在一个线程上返回后,另一个线程可能正在将 item 状态更新为另一个值,这可能会破坏 item 状态的业务逻辑。

一个简单的解决方案是让组件 A 和组件 B 锁定在同一个共享对象上。从设计的角度来看,如何在组件之间共享这个对象(每个组件都有不同的目的)?

我看到的另一个解决方案是为了同步调用而拥有一个同时执行组件 A 和组件 B 的业务逻辑的服务,但我认为这不是一个好的解决方案。

我正在寻找比这些更好的实现。

我的感觉是一个很好的解决方案可能是一个允许我在上下文中运行事物的解决方案。就像是

   ItemSyncContext.Run(ExecuteUpdateItemCommand);

   ItemSyncContext.Run(OnNotificationReceived);      

标签: c#multithreadingdesign-patternsthread-safetythread-synchronization

解决方案


理想情况下,您只需调用一次即可完成这两项更新的服务。如果这不是一个选项,您需要回答“更新何时发生?”的问题。在服务中。如果调用是阻塞的,所以在调用返回之前提交更新,你可以安全地保持你的代码原样。否则,您需要研究某种机制(即锁定)以确保调用以正确的顺序发生。


推荐阅读