首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >.NET中的可变新鲜度保证(易失性与易失性读取)

.NET中的可变新鲜度保证(易失性与易失性读取)
EN

Stack Overflow用户
提问于 2014-07-10 21:25:45
回答 1查看 2.3K关注 0票数 17

我读过很多相互矛盾的信息(msdn,SO等)。关于易失性和VoletileRead (ReadAcquireFence)。

我理解那些内存访问重新排序限制的含义--我仍然完全不明白的是新鲜度保证--这对我来说非常重要。

msdn doc for volatile提到:

(...)这可确保字段中始终显示最新的值。

msdn doc for volatile fields提到:

对易失性字段的读取称为易失性读取。易失性读取具有“获取语义”;也就是说,它保证发生在指令序列中它之后发生的任何对内存的引用之前。

.NET code for VolatileRead是:

代码语言:javascript
复制
public static int VolatileRead(ref int address)
{
    int ret = address;
    MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
    return ret;
}

根据msdn MemoryBarrier doc内存屏障防止重新排序。然而,这似乎对新鲜度没有任何影响-对吗?

那么如何才能得到保鲜度呢?标记字段易失性与使用VolatileRead和VolatileWrite语义访问它有什么不同?我目前正在做我的性能关键代码的后期工作,需要保证新鲜度,但是读者有时会得到陈旧的价值。我想知道,如果将状态标记为易失性,情况是否会有所不同。

EDIT1:

我想要实现的是--确保读取器线程将获得尽可能多的共享变量(由多个写入器编写)的最新值-理想情况下,不会超过上下文切换或其他可能延迟状态直接写入的操作的成本。

如果易失性或更高级别的构造(例如锁)有这个保证(它们有吗?)那么他们如何做到这一点呢?

EDIT2:

非常简洁的问题应该是-如何保证在读取过程中获得尽可能新的值??理想情况下不需要锁定(因为不需要独占访问,并且存在高争用的可能性)。

根据我在这里学到的东西,我想知道这是否可能是解决方案(解决(?)行用注释标记):

代码语言:javascript
复制
private SharedState _sharedState;
private SpinLock _spinLock = new SpinLock(false);

public void Update(SharedState newValue)
{
    bool lockTaken = false;
    _spinLock.Enter(ref lockTaken);

    _sharedState = newValue;

    if (lockTaken)
    {
        _spinLock.Exit();
    }
}

public SharedState GetFreshSharedState
{
    get
    {
        Thread.MemoryBarrier(); // <---- This is added to give readers freshness guarantee
        var value = _sharedState;
        Thread.MemoryBarrier();
        return value;
    }
}

添加MemoryBarrier调用是为了确保读取和写入都被完全隔离(与锁定代码相同-如此处的“内存障碍和锁定”部分所示)。

看起来是正确的还是有缺陷的?

EDIT3:

多亏了这里非常有趣的讨论,我学到了相当多的东西,实际上我能够提炼出关于这个主题的简单而明确的问题。它与原来的版本有很大的不同,所以我在这里发布了一个新版本:

EN

回答 1

Stack Overflow用户

发布于 2014-07-10 22:10:11

内存屏障确实提供了这种保证。我们可以从屏障保证的记录属性中派生出您正在寻找的“新鲜度”属性。

所谓新鲜度,您可能是指读取操作返回最近一次写入的值。

假设我们有这些操作,每个操作都在不同的线程上:

代码语言:javascript
复制
x = 1
x = 2
print(x)

我们怎么可能打印出2以外的值呢?如果不使用易失性,读操作可以向上移动一个槽并返回1。易失性会阻止重新排序。写入不能在时间上向后移动。

简而言之,易失性保证您可以看到最新的值。

严格地说,在这里我需要区分易失性和内存屏障。后者是更有力的保证。我简化了这个讨论,因为volatile是使用内存屏障实现的,至少在x86/x64上是这样。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24677773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档