【发布时间】:2021-04-17 11:10:49
【问题描述】:
我尝试像这样用 C# 实现彼得森锁
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;
}
}
- 不知道这两行是否都需要?
- 是否有任何规则可以帮助我判断哪一行将被重新排序,哪一行 行不会?
- 什么时候应该使用内存屏障?
【问题讨论】:
-
“但是当我在 2 个线程中使用这个锁时,它不起作用” - “不起作用”是什么意思?您是否尝试在两个线程中使用此锁,但两个线程同时进入临界区?或者是什么?请出示您的“测试”代码。
标签: c# mutex lock-free memory-barriers instruction-reordering