代码之家  ›  专栏  ›  技术社区  ›  user3205479

在组级别而不是应用程序级别处理并发

  •  0
  • user3205479  · 技术社区  · 4 年前

    我想处理API中的并发问题。在这种情况下,我们从同一个组的多个用户那里得到一个请求。也可以有多个组。下面的解决办法我认为应该管用,请指正

     // This will be a singleton across the API
     ConcurrentDictionary<string, string> dict = new ConcurrentDictionary<string, string>();
    
     if (dict.ContainsKey(groupId)) {
        throw new Exception("request already accepted");
     } else {
         // Thinking this is thread lock operation or i can put lock statement
         if(dict.TryAdd(groupId, "Added") == false) {
            throw new Exception("request already accepted");
         }
         // continue the original logic
     }
    

    每10分钟后,我们将清除字典中的旧密钥(注意此操作应正常工作,即线程未锁定模式,因为它将在已使用的旧密钥上工作)。并发字典在键级而不是字典级有线程锁定吗?因此,我们不会阻止所有请求,而是只阻止与组相关的特定请求。非常感谢您的帮助。

    一个快速的解决方案是在周围安装锁包装器 get add 但这将阻止所有请求继续进行,我们希望在组级别阻止。非常感谢您的帮助。

    0 回复  |  直到 4 年前
        1
  •  0
  •   Carlos Garcia    4 年前

    将内容添加到并发字典是一个非常快速的操作。您也没有让线程等待第一个线程完成,如果它们无法获得锁,您将立即丢弃。

    这让我觉得 Double Checked Lock

    所以,我只需要做你的内部检查,不需要外部检查:

    
    
    
    if(dict.TryAdd(groupId, "Added") == false) 
    {
            throw new Exception("request already accepted");
    }
    

    will not lock

    另一个有趣的话题是如何清理这个。

    // NOTE: THIS IS JUST PSEUDOCODE
    
    // In your controller, you can simply do this...
    //
    public SomeController()
    {
    
        using (var operation = new GroupOperation(groupId)) 
        {
            // In here I am sure I am the only operation of this group
        } 
    
        // In here I am sure that the operation got removed from the dictionary
    
    }
    
    
    // This class hides all the complexity of the concurrent dictionary
    //
    public class GroupOperation : IDisposable
    {
        var singletonDictionary = new ConcurrentDictionary<int,int>()
        int GroupId;
    
        public GroupOperation(int GroupID)
        {
             this.GroupId = GroupId;
             if(!singletonDictionary.TryADd(GroupID, 1))
             {
                 throw new Exception("Sorry, operation in progress for your group");
             }
        }
    
        protected virtual void Dispose(bool disposing)
        {
           singletonDictionary.Remove(GroupId)
        }
    }