MemoryBarrier是否保证所有内存的内存可见性? [英] Does a MemoryBarrier guarantee memory visibility for all memory?

查看:81
本文介绍了MemoryBarrier是否保证所有内存的内存可见性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我正确理解,在C#中,lock块可保证对一组指令的独占访问,但也可保证从内存中进行的任何读取均反映该内存在任何CPU高速缓存中的最新版本.我们认为lock块可以保护在块内读取和修改的变量,这意味着:

If I understand correctly, in C#, a lock block guarantees exclusive access to a set of instructions, but it also guarantees that any reads from memory reflect the latest version of that memory in any CPU cache. We think of lock blocks as protecting the variables read and modified within the block, which means:

  1. 假设您已在必要的地方正确实现了锁定,则这些变量一次只能由一个线程读写,并且
  2. lock块中的读取可查看变量的最新版本,lock块中的写入对所有线程可见.
  1. Assuming you've properly implemented locking where necessary, those variables can only be read and written to by one thread at a time, and
  2. Reads within the lock block see the latest versions of a variable and writes within the lock block become visible to all threads.

(对吗?)

第二点是我感兴趣的.是否有某种魔术可以保证仅在受lock块保护的代码中读写仅变量,或者在实现lock时采用的内存屏障可以保证 all 现在所有线程的内存都一样新鲜吗?在这里请谅解关于缓存如何工作的精神上的困惑,但是我读到缓存包含几条多字节的行"数据.我想我要问的是,内存屏障是否会强制全部 个脏"高速缓存行同步,或者只是同步一些,如果只是同步,是什么决定了哪些行要同步?

This second point is what interests me. Is there some magic by which only variables read and written in code protected by the lock block are guaranteed fresh, or do the memory barriers employed in the implementation of lock guarantee that all memory is now equally fresh for all threads? Pardon my mental fuzziness here about how caches work, but I've read that caches hold several multi-byte "lines" of data. I think what I'm asking is, does a memory barrier force synchronization of all "dirty" cache lines or just some, and if just some, what determines which lines get synchronized?

推荐答案

锁块中的读取可查看变量的最新版本,锁块中的写入对所有线程可见.

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

不,这绝对是一种过分简化的有害行为.

No, that's definitely a harmful oversimplification.

当您输入lock语句时,会有一个内存栅栏,其中表示您将始终读取新"数据.当退出lock状态时,会出现一个内存隔离区,其中表示保证已写入的所有数据都将被写入主内存并可供其他线程使用.

When you enter the lock statement, there a memory fence which sort of means that you'll always read "fresh" data. When you exit the lock state, there's a memory fence which sort of means that all the data you've written is guaranteed to be written to main memory and available to other threads.

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

The important point is that if multiple threads only ever read/write memory when they "own" a particular lock, then by definition one of them will have exited the lock before the next one enters it... so all those reads and writes will be simple and correct.

如果您的代码可以在没有锁的情况下读写变量 ,则无法保证它会查看"行为良好的代码(例如,使用锁的代码)写入的数据,否则行为良好的线程将看到"由该错误代码编写的数据.

If you have code which reads and writes a variable without taking a lock, then there's no guarantee that it will "see" data written by well-behaved code (i.e. code using the lock), or that well-behaved threads will "see" the data written by that bad code.

例如:

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;
}

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

Now it's more subtle than that, but that's why using a common lock to protect a set of variables works.

这篇关于MemoryBarrier是否保证所有内存的内存可见性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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