通过lock语句内存屏障 [英] Memory Barrier by lock statement

查看:511
本文介绍了通过lock语句内存屏障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近读到内存壁垒和重新排序的问题,我现在有一些关于它的困惑



考虑以下情形:

 私有对象_object1 = NULL; 
私有对象_object2 = NULL;
私人布尔_u​​singObject1 = FALSE;

私有对象为MyObject
{
得到
{
如果(_usingObject1)
{
返回_object1;
}
,否则
{
返回_object2;
}
}

{
如果(_usingObject1)
{
_object1 =价值;
}
,否则
{
_object2 =价值;
}
}
}

私人无效更新()
{
_usingMethod1 = TRUE;
SomeProperty = FooMethod();
// ..
_usingMethod1 = FALSE;
}




  1. 更新方法;在 _usingMethod1 = TRUE 语句总是获取或设置属性之前执行的?或由于重新排序问题,我们能不能​​保证?


  2. 如果我们使用挥发性

     私人挥发性布尔_usingMethod1 = FALSE; 


  3. 如果我们使用锁; 我们可以保证再锁内的每一个语句才能等来执行:

     私人无效FooMethod()
    {
    对象更衣室=新的对象();
    锁(柜)
    {
    X = 1;
    Y = A;
    I ++;
    }
    }



解决方案

记忆障碍的主题是相当复杂的。它甚至绊倒了专家不时。当我们谈论一个内存屏障,我们真的是结合两种不同的思路。




  • 获取围栏:内存屏障中,其他读取和放大器;写不准动的的围栏

  • 发布栅栏:A内存屏障中,其他读取和放大器;写不准动的之后的围栏。



这将创建一个内存屏障只有两个一个是有时也被称为的半护栏的。创建两个有时也被称为内存屏障的全栅栏



挥发性关键字创建半围栏。挥发性领域具有读取语义收购而写有释放的语义。这意味着没有指令可以读取之前或写操作后移动。



锁定关键字创建全栅栏两个边界(入口和出口)。这意味着没有指令可以每个边界之前或之后进行移动。



然而,这一切都没有实际意义,如果我们只关注一个线程。订货,因为它是由该线程感知,总是保留。事实上,如果没有这个基本机制保障没有程序将永远工作的权利。真正的问题是用的其他的主题是如何看待的读取和写入。 。这就是你需要关心



因此​​,要回答你的问题:




  1. 从单一线程的角度来看......是的。从另一个线程的角度看...没有。


  2. 这要看情况。这可能工作,但我需要有更好的理解你正在试图acheive什么。


  3. 从另一个线程的角度看...没有。的读取和写入可自由锁定的边界内移动。他们只是无法将这些范围之外移动。这就是为什么它是其他线程同时创建内存屏障重要的。



I read recently about memory barriers and the reordering issue and now I have some confusion about it.

Consider the following scenario:

private object _object1 = null;    
private object _object2 = null;
private bool _usingObject1 = false;

private object MyObject
{
    get 
    {
        if (_usingObject1)
        {
            return _object1;
        }
        else
        {
            return _object2;
        }
    }
    set 
    {
        if (_usingObject1)
        {
           _object1 = value;
        }
        else
        {
           _object2 = value;
        }
    }
}

private void Update()
{
    _usingMethod1 = true;
    SomeProperty = FooMethod();
    //..
    _usingMethod1 = false;
}

  1. At Update method; is the _usingMethod1 = true statement always executed before getting or setting the property? or due to reordering issue we can not guarantee that?

  2. Should we use volatile like

    private volatile bool _usingMethod1 = false;
    

  3. If we use lock; can we guarantee then every statement within the lock will be executed in order like:

    private void FooMethod()
    {
        object locker = new object();
        lock (locker)
        {
            x = 1;
            y = a;
            i++;
        }
    }
    

解决方案

The subject of memory barriers is quite complex. It even trips up the experts from time to time. When we talk about a memory barrier we are really combining two different ideas.

  • Acquire fence: A memory barrier in which other reads & writes are not allowed to move before the fence.
  • Release fence: A memory barrier in which other reads & writes are not allowed to move after the fence.

A memory barrier that creates only one of two is sometimes called a half-fence. A memory barrier that creates both is sometimes called a full-fence.

The volatile keyword creates half-fences. Reads of volatile fields have acquire semantics while writes have release semantics. That means no instruction can be moved before a read or after a write.

The lock keyword creates full-fences on both boundaries (entry and exit). That means no instruction can be moved either before or after each boundary.

However, all of this moot if we are only concerned with one thread. Ordering, as it is perceived by that thread, is always preserved. In fact, without that fundamental guarentee no program would ever work right. The real issue is with how other threads perceive reads and writes. That is where you need to be concerned.

So to answer your questions:

  1. From a single thread's perspective...yes. From another thread's perspective...no.

  2. It depends. That might work, but I need to have better understanding of what you are trying to acheive.

  3. From another thread's perspective...no. The reads and writes are free to move around within the boundaries of the lock. They just cannot move outside those boundaries. That is why it is important for other threads to also create memory barriers.

这篇关于通过lock语句内存屏障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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