加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#懒惰和竞赛初始化?

发布时间:2020-12-16 01:51:39 所属栏目:百科 来源:网络整理
导读:(在问了 this related question 之后,我还有一个问题.) 使用Lazy T的整个想法(AFAIK).,是仅在我们需要时才创建对象. 为什么?因为创建它很昂贵. 我想要的最后一件事是,将创建昂贵的对象 1次. 我不在乎许多线程最终会产生相同的引用.我只是不希望他们创建多个
(在问了 this related question 之后,我还有一个问题.)

使用Lazy< T>的整个想法(AFAIK).,是仅在我们需要时才创建对象.
为什么?因为创建它很昂贵.

我想要的最后一件事是,将创建昂贵的对象> 1次.

我不在乎许多线程最终会产生相同的引用.我只是不希望他们创建多个实例.

所以Lazyinitializer通过syncLock处理这个:

LazyInitializer.EnsureInitialized (ref _expensive,ref useless,ref _sync,() => new Expensive());

但是Lazy< T>是什么?可以处理吗?
我在msdn中搜索过,无法找到任何syncLock重载…

我错过了什么?

解决方法

你在问懒惰是如何在内部工作的吗?根据 MSDN documentation,Lazy确保只创建一个:

By default,Lazy objects are thread-safe. That is,if the constructor
does not specify the kind of thread safety,the Lazy objects it
creates are thread-safe. In multi-threaded scenarios,the first thread
to access the Value property of a thread-safe Lazy object initializes
it for all subsequent accesses on all threads,and all threads share
the same data. Therefore,it does not matter which thread initializes
the object,and race conditions are benign.

如果您实际上询问它是如何在内部工作的,那么它似乎正在使用某种锁:

object obj = Volatile.Read<object>(ref this.m_threadSafeObj);
        bool flag = false;
        try
        {
            if (obj != Lazy<T>.ALREADY_INVOKED_SENTINEL)
            {
                Monitor.Enter(obj,ref flag);
            }
            if (this.m_boxed == null)
            {
                boxed = this.CreateValue();
                this.m_boxed = boxed;
                Volatile.Write<object>(ref this.m_threadSafeObj,Lazy<T>.ALREADY_INVOKED_SENTINEL);
            }
            else
            {
                boxed = (this.m_boxed as Lazy<T>.Boxed);
                if (boxed == null)
                {
                    Lazy<T>.LazyInternalExceptionHolder lazyInternalExceptionHolder = this.m_boxed as Lazy<T>.LazyInternalExceptionHolder;
                    lazyInternalExceptionHolder.m_edi.Throw();
                }
            }
        }
        finally
        {
            if (flag)
            {
                Monitor.Exit(obj);
            }
        }

注意Monitor.Enter和Monitor.Exit调用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读