栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

系统懒惰 具有不同的线程安全模式

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

系统懒惰 具有不同的线程安全模式

我尝试的是达林更新后的答案版本,但没有我指出的比赛条件…警告,我不确定这最终是否完全摆脱了比赛条件。

private static int waiters = 0;private static volatile Lazy<object> lazy = new Lazy<object>(GetValueFromSomewhere);public static object Value{    get    {        Lazy<object> currLazy = lazy;        if (currLazy.IsValueCreated) return currLazy.Value;        Interlocked.Increment(ref waiters);        try        { return lazy.Value; // just leave "waiters" at whatever it is... no harm in it.        }        catch        { if (Interlocked.Decrement(ref waiters) == 0)     lazy = new Lazy<object>(GetValueFromSomewhere); throw;        }    }}

更新:我以为发布此消息后发现了比赛情况。该行为实际上应该是可以接受的,只要您对一个罕见的情况感到满意,即

Lazy<T>
在另一个线程已经从成功的快速返回之后,某个线程抛出了一个从慢速观察到的异常
Lazy<T>
(将来的请求将全部成功)。

  • waiters
    = 0
  • t1:一直运行到
    Interlocked.Decrement
    waiters
    = 1)之前
  • t2:进入并运行到
    Interlocked.Increment
    waiters
    = 1)之前
  • t1:进行
    Interlocked.Decrement
    并准备覆盖(
    waiters
    = 0)
  • t2:一直运行到
    Interlocked.Decrement
    waiters
    = 1)之前
  • t1:
    lazy
    用新的覆盖(称为
    lazy1
    )(
    waiters
    = 1)
  • t3:进入并在
    lazy1
    waiters
    = 2)处阻止
  • t2:是否执行
    Interlocked.Decrement
    waiters
    = 1)
  • t3:从
    lazy1
    waiters
    现在不相关)获取并返回值
  • t2:抛出异常

我无法提出一系列导致比“该线程在另一个线程产生成功结果之后引发异常”更糟糕的事情的事件。

Update2:声明

lazy
volatile
确保所有读者立即都能看到受保护的覆盖。有些人(包括我自己在内)看到
volatile
并立即想到“好吧,可能是使用不正确”,他们通常是正确的。这就是我在这里使用它的原因:在上面示例中的事件序列中,t3仍然可以读取旧的,
lazy
而不是
lazy1
如果它位于
lazy.Value
t1修改
lazy
为包含的那一刻之前
lazy1

volatile
防止这种情况,以便下次尝试可以立即开始。

我还提醒自己,为什么我脑子里有这样的话:“低锁并发编程很难,只需使用C#

lock
语句!!!” 我一直在写原始答案。

Update3:只是更改了Update2中的一些文本,指出了

volatile
必要的实际情况-
Interlocked
此处使用的操作显然是在当今重要的CPU架构上全屏实现的,而不是我最初只是假设的半屏实现的,因此
volatile
保护的范围比我原来想象的要窄得多。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/415331.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号