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

c# – MemoryBarrier是否保证所有内存的内存可见性?

发布时间:2020-12-15 19:27:45 所属栏目:百科 来源:网络整理
导读:如果我理解正确,在C#中,锁定块保证对一组指令的独占访问,但它也保证从内存中的任何读取都反映了任何CPU缓存中该内存的最新版本.我们将锁定块视为保护块内读取和修改的变量,这意味着: 假设您已经在必要时正确实现了锁定,那么这些变量一次只能由一个线程读取
如果我理解正确,在C#中,锁定块保证对一组指令的独占访问,但它也保证从内存中的任何读取都反映了任何CPU缓存中该内存的最新版本.我们将锁定块视为保护块内读取和修改的变量,这意味着:

>假设您已经在必要时正确实现了锁定,那么这些变量一次只能由一个线程读取和写入,并且
>在锁定块中读取,查看变量的最新版本,并且锁定块内的写入对所有线程都可见.

(对?)

第二点是我感兴趣的.是否存在一些魔法,只有在锁定块保护的代码中读取和写入的变量才能保证新鲜,或者锁定实现中使用的内存屏障是否保证所有内存现在对所有线程都同样新鲜?请原谅我在这里关于缓存如何工作的心理模糊性,但我已经读过缓存中存有几个多字节“数据线”.我想我要问的是,内存屏障是否强制同步所有“脏”缓存行或只是一些,如果只是一些,是什么决定了哪些行同步?

解决方法

Reads within the lock block see the latest versions of a variable and writes within the lock block are visible to all threads.

不,这绝对是一个有害的过度简化.

当你输入lock语句时,会有一个内存栅栏,这意味着你将始终读取“新鲜”数据.当你退出锁定状态时,会有一个内存栏,这意味着你所写的所有数据都保证被写入主内存并可供其他线程使用.

重要的一点是,如果多个线程只有在“拥有”特定锁时才读/写内存,那么根据定义,其中一个将在下一个进入之前退出锁…所以所有这些读写都将简单而正确.

如果你有代码在没有锁定的情况下读取和写入变量,那么就不能保证它会“看到”由行为良好的代码(即使用锁的代码)写入的数据,或者表现良好的线程将“看到”这个坏代码写的数据.

例如:

private readonly object padlock = new object();
private int x;

public void A()
{
    lock (padlock)
    {
        // Will see changes made in A and B; may not see changes made in C
        x++;
    }
}

public void B()
{
    lock (padlock)
    {
        // Will see changes made in A and B; may not see changes made in C
        x--;
    }
}

public void C()
{
    // Might not see changes made in A,B,or C. Changes made here
    // might not be visible in other threads calling A,B or C.
    x = x + 10;
}

现在它比这更微妙,但这就是为什么使用公共锁来保护一组变量的原因.

(编辑:李大同)

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

    推荐文章
      热点阅读