微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我什么时候应该考虑内存屏障和指令重新排序?

如何解决我什么时候应该考虑内存屏障和指令重新排序?

我尝试像这样用 C# 实现 Peterson Lock

public class PetersonLock
{
    private volatile bool[] flag = new bool[2];
    private volatile int victim;
    public int oneThreadId;

    public void Lock() {
        int i = Thread.CurrentThread.ManagedThreadId == oneThreadId ? 1 : 0;
        int j = 1 - i;
        flag[i] = true; /* A */
        victim = i;     /* B */
        while (flag[j] && victim == i) { } /* C */
    }

    public void Unlock() {
        int i = Thread.CurrentThread.ManagedThreadId == oneThreadId ? 1 : 0;
        flag[i] = false;
    }
}

但是当我在 2 个线程中使用这个锁时,它不起作用,有人说我应该考虑指令重新排序并使用内存屏障。 A线、B线和C线是否像A->B->C,或A->C->B,或C->A->B或其他顺序一样重新排序?所以我把我的代码改成这样:

public class PetersonLock
{
    private volatile bool[] flag = new bool[2];
    private volatile int victim;
    public int oneThreadId;

    public void Lock() {
        int i = Thread.CurrentThread.ManagedThreadId == oneThreadId ? 1 : 0;
        int j = 1 - i;
        flag[i] = true;
        Thread.MemoryBarrier(); // Is this line nesscessary?
        victim = i;
        Thread.MemoryBarrier(); // Is this line nesscessary?
        while (flag[j] && victim == i) { }
    }

    public void Unlock() {
        int i = Thread.CurrentThread.ManagedThreadId == oneThreadId ? 1 : 0;
        flag[i] = false;
    }
}
  • 不知道这两行是不是都需要?
  • 有什么规则可以帮助我判断哪一行会被重新排序,哪一行会被重新排序? 行不会?
  • 我应该什么时候使用内存屏障?

解决方法

根据Microsoft Documentation,有更简单的方法可以使用锁和Monitor 类来同步代码。 如果您仍想坚持使用 Thread.MemoryBarrier,我发现这个 link 非常有趣。

关于你的代码,我对 PetersonLock 不是很熟悉,所以不要盲目相信我的话。我会说第一个屏障用于确保在设置受害者之前设置标志,并且需要第二个屏障将内存刷新到所有缓存的内存行,以便所有线程读取相同的值

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。