public class Test 
    {
private object syncRoot = new object();        private volatile Dictionary<int, Dict<int, int>> _userIds;         /// <summary>
        /// 索引属性:字典对象
        /// </summary>
        public Dict<int, int> this[int id]
        {
            get
            {
                // 检查有无初始化对象
                if (_userIds == null)
                    _userIds = new Dictionary<int, Dict<int, int>>();                // 如果字典中没有则从数据库载入对象
                if (!_userIds.ContainsKey(id))
                {
                    lock (syncRoot)
                    {
                        // 锁住后再次确认是否没有对应的分类字典 
                        if (!_userIds.ContainsKey(id))
                        {
                            _userIds[id] = Offers.GetUserOfferIds(this.UserID, 2, id);
                        }
                    }
                }                return _userIds[id];
            }            set
            {
                // 先检查对应的缓存是否存在?
                if (_userIds!=null && _userIds.ContainsKey(id))
                {
                    lock (syncRoot)
                    {
                        _userIds.Remove(id); 
                    }
                }
            }
        }     ...
    }

解决方案 »

  1.   

    暂时没测出来有问题,但是实际应用时,发现1个星期内偶尔出现一次问题比较头大,不知道程序上是否有BUG
      

  2.   

    get
    {
     lock (syncRoot)
      {
    ...}
    }
    set
    {
       lock (syncRoot)
      {
    ...
    }
    lock应该紧挨属性访问器
      

  3.   

    lock 把程序都包进去, 安全性是比较高,但会导致并发性下降利害,因此实际上微软企业库的示例都没有采用这种传统lock方式。
      

  4.   

     
    // 检查有无初始化对象
      if (_userIds == null)
      _userIds = new Dictionary<int, Dict<int, int>>();
    感觉这段有问题
    虽然_userIds 用volatile 修饰,但依赖其旧值无法保证其线程安全。
    在执行userIds = new Dictionary<int, Dict<int, int>>();
    之前,有可能两个线程同时通过 if (_userIds == null)
    。可能会有两次new。