【发布时间】:2016-09-05 21:16:17
【问题描述】:
我正在试验不需要原子指令的锁。彼得森的算法似乎是最简单的起点。但是,如果迭代次数足够多,就会出现问题。
代码:
public class Program
{
private static volatile int _i = 0;
public static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
RunTest();
}
Console.Read();
}
private static void RunTest()
{
_i = 0;
var lockType = new PetersonLock();
var t1 = new Thread(() => Inc(0, lockType));
var t2 = new Thread(() => Inc(1, lockType));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine(_i);
}
private static void Inc(int pid, ILock lockType)
{
try
{
for (int i = 0; i < 1000000; i++)
{
lockType.Request(pid);
_i++;
lockType.Release(pid);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public interface ILock
{
void Request(int pid);
void Release(int pid);
}
public class NoLock : ILock
{
public void Request(int pid) { }
public void Release(int pid) { }
}
public class StandardLock : ILock
{
private object _sync = new object();
public void Request(int pid)
{
Monitor.Enter(_sync);
}
public void Release(int pid)
{
Monitor.Exit(_sync);
}
}
public class PetersonLock : ILock
{
private volatile bool[] _wantsCs = new bool[2];
private volatile int _turn;
public void Request(int pid)
{
int j = pid == 1 ? 0 : 1;
_wantsCs[pid] = true;
_turn = j;
while (_wantsCs[j] && _turn == j)
{
Thread.Sleep(0);
}
}
public void Release(int pid)
{
_wantsCs[pid] = false;
}
}
当我运行它时,我始终得到
【问题讨论】:
-
会不会是您使用了
private int _turn;而不是private volitile int _turn;,并且您遇到了cpu 缓存问题? -
@ScottChamberlain 刚试过,好像没什么影响
-
添加一个异常处理程序(try/catch)以查看您是否收到任何异常。程序可能只是由于异常而终止。
-
这里的问题是
_wantsCs[pid] = true;和_turn = j;被重新排序了。尝试在两者之间添加Thread.MemoryBarrier();,您应该会得到正确的结果。 -
@jdweng 他正在加入线程,这意味着他将等待两个线程完全执行完。他还传递了两个不同的
pid值。
标签: c# multithreading locking