实现对无锁保证64位架构长期性的线程安全的原子访问的最佳方式 [英] Best way to implement thread safe atomic accessors of a long property on a guaranteed 64 bit architecture without lock

查看:147
本文介绍了实现对无锁保证64位架构长期性的线程安全的原子访问的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个属性的类型是长(Int64的)。

I have a property its type is long (Int64).

如果这将是一个int,那么我可以宣布支持字段为:

If it would be an int, then I could declare the backing field as:

private volatile int _myInt;

和创建一个简单的get和set访问。

and create a simple get and set accessor.

不过C#编译器不允许使用volatile关键字长的类型,即使有64项目设置。所以,这种情况是,即使我们相信,读/写操作是原子的这一变量,遗憾的是一种危险,即一个线程读取该变量将得到和使用的方式旧的(处理器或CLR / JIT优化器)的缓存值......

However the C# compiler does not allow using the volatile keyword with the type long, even with the x64 project settings. So the situation is that even we are sure that the read/write operations are atomic on this variable, unfortunately there is a danger that a thread which reads the variable will get and use a way old (processor or CLR/JIT optimizer) cached value...

问题1:这是指而不是简单地看这个值的get访问,我必须使用连锁,prevent读取缓存值

Question1: Is this means that instead of simply reading this value in the get accessor I have to use Interlocked to prevent reading a cached value?

get
{
    return Interlocked.CompareExchange(ref _myLong, 0, 0);
}

这意味着相当的开销......

This means a quite overhead...

问题2:假设还是有保证的64位架构,是否足够像set访问一个简单的任务:

Question2: Still supposing a guaranteed 64 bit architecture, Is it enough a simple assignment in the set accessor like:

set
{
    _myLong = value;
}

在此先感谢

推荐答案

您可以使用<一个href="http://msdn.microsoft.com/en-us/library/system.threading.volatile%28v=vs.110%29.aspx">System.Threading.Volatile类来解决这个问题。例如:

You can use the System.Threading.Volatile class to solve this problem. For example:

class Example {
    private long _prop;
    public long prop {
        get { return Volatile.Read(ref _prop); }
        set { Volatile.Write(ref _prop, value); }
    }
}

虽然这的看起来的低效它实际上产生在x64处理器的高效code。抖动内置了挥发类的知识,并直接转换到机code,而不是依赖于框架实现。而64位抖动知道的的是原子在64位的Intel / AMD处理器。例如:

While this looks inefficient it in fact generates highly efficient code on a x64 processor. The jitter has built-in knowledge of the Volatile class and directly translates it to machine code instead of relying on the framework implementation. And the x64 jitter knows that long is atomic on a 64-bit Intel/AMD processor. For example:

    static void Main(string[] args) {
        var obj = new Example();
        obj.prop = 42;
        Console.WriteLine(obj.prop);
    }

生成此机code:

Generates this machine code:

00007FFA3DF43AB0  sub         rsp,28h                     ; setup stack frame
00007FFA3DF43AB4  lea         rcx,[7FFA3DF959B0h]         ; obj = new Example
00007FFA3DF43ABB  call        00007FFA9D5A2300  
00007FFA3DF43AC0  mov         qword ptr [rax+8],2Ah       ; obj.prop setter
00007FFA3DF43AC8  mov         rcx,qword ptr [rax+8]       ; obj.prop getter
00007FFA3DF43ACC  call        00007FFA9CD0CFD0            ; Console.WriteLine
00007FFA3DF43AD1  nop                                     ; alignment
00007FFA3DF43AD2  add         rsp,28h                     ; destroy stack frame
00007FFA3DF43AD6  ret                                     ; done

和注意属性如何getter和setter被完全消除,直接访问Example._prop领域。这是你所期待的。如果你在使用内存模型弱,如ARM处理器运行此code,那么它仍然会正确地与相应的采集工作,并释放语义如何产生的,所要求的这样的处理器。

And note how the property getter and setter were completely eliminated, accessing the Example._prop field directly. Which is what you were looking for. If you ever run this code on a processor with a weak memory model, like ARM, then it will still work correctly with the appropriate acquire and release semantics getting generated, as required by such a processor.

这篇关于实现对无锁保证64位架构长期性的线程安全的原子访问的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆