You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ReaderWriterLockSlim锁定函数参数以解决索引越界问题

问题描述

Class1基于后端JSON流创建动态静态对象dynamObj,更新dynamObj时使用锁。Class2获取该dynamObj做进一步处理,但遍历其数组类型属性时偶尔触发索引越界异常。现提出以下问题:

  1. 在Class2中,当Method2(dynamObjCopy)执行期间,若原始静态dynamObj被更新,dynamObjCopy参数会自动更新吗?换句话说,while循环执行时PropertyArray的Length是否会变化?
  2. 若这是索引越界的原因,如何锁定Method2的参数dynamObjCopy以阻止其更新?像Class1那样锁定Method2整个函数体是否可行?

简化示例代码

public class Class1
{
   public static dynamic dynamObj = null;
   public static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

   try
   { 
     locker.EnterWriteLock();
     dynamObj = deserializedDynamObjFromJSONstream;
   }
   finally
   {
     locker.ExitWriteLock();
   }
}

public class Class2
{
   public dynamic Method1()
   {
    dynamic dynamObjCopy = dynamObj;

    Method2(dynamObjCopy);
   }

   private dynamic Method2(dynamic dynamObjCopy)
   {
      var ind = 0;
      while (ind < dynamObjCopy.PropertyArray.Length)
      {// 此处偶尔触发索引越界异常
         someList.Add(dynamObjCopy.PropertyArray[ind]);
         ind++;
      }
   }
}
问题解答

问题1解答

分两种情况:

  • 如果Class1更新dynamObj是直接替换整个对象引用(如示例代码中dynamObj = deserializedDynamObjFromJSONstream),那dynamObjCopy会保留旧对象的引用,其PropertyArray的Length不会随新dynamObj变化,理论上不会触发索引越界。
  • 如果更新操作是修改原有dynamObj内部的PropertyArray实例(比如直接缩短数组、替换数组引用),那dynamObjCopy因为指向同一个对象实例,遍历过程中PropertyArray的Length可能突然变小,导致索引越界。

问题2解答

锁定dynamObjCopy本身没用,它只是个引用。核心是要保证读取dynamObj及其内部属性的全程,不会有写入操作修改目标对象:

  1. 复用Class1的ReaderWriterLockSlim锁,在读取+遍历的全流程加读锁:
    必须在获取对象引用到完成遍历的整个阶段持有读锁,确保Class1的写锁无法抢占,避免对象被修改。示例代码调整如下:
    public dynamic Method1()
    {
        Class1.locker.EnterReadLock();
        try
        {
            var someList = new List<object>();
            var ind = 0;
            while (ind < Class1.dynamObj.PropertyArray.Length)
            {
                someList.Add(Class1.dynamObj.PropertyArray[ind]);
                ind++;
            }
            return someList;
        }
        finally
        {
            Class1.locker.ExitReadLock();
        }
    }
    
  2. 若一定要用副本,需在锁内创建深拷贝:浅拷贝只会复制对象引用,内部的PropertyArray仍指向同一个实例,依然可能被修改。
  3. 单独锁定Method2整个函数体不可行:如果用新锁,无法和Class1的写锁同步;如果用Class1的锁,dynamObjCopy可能在Method1获取时就已处于“待修改”状态,锁无法覆盖从获取引用到进入Method2的这段空白期。

内容的提问来源于stack exchange,提问作者user2217057

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:42:32