c# Lock 不起作用/关键部分
c# Lock Doesn`t work / Critical Section
我正在尝试在 FOR 循环中使用两个不同的线程来推进静态 (int) 计数器,因此如果循环是 运行s 10 倍我 (should) 得到计数器=20。出于某种原因,我每次 运行 循环 (19,20,21) 时都会得到不同的值,即使我使用 LOCK 访问该计数器,(控制台中的代码 运行s):
public static int Counter = 0;
static object syncObject = new object();
static void Main(string[] args)
{
int ForLength = 10;
Thread FirstThread, SecondThread;
for (int i = 0; i <= ForLength; i++)
{
FirstThread = new Thread(RaiseCounter);
FirstThread.IsBackground = false;
SecondThread = new Thread(RaiseCounter);
SecondThread.IsBackground = false;
FirstThread.Start();
SecondThread.Start();
//Console.WriteLine(Counter);
}
Console.WriteLine(Counter);
Console.ReadLine();
}
public static void RaiseCounter ()
{
lock (syncObject)
{
Counter++;
}
}
你遇到了三个问题:
你实际上 运行 循环 11 次:
for (int i = 0; i <= ForLength; i++) // i=0 to i=10 *inclusive*
您没有加入线程(或休眠),因此在您编写输出时其中一些线程可能尚未完成
当您在主线程中读取 Counter
时,您没有在 syncObject
上进行同步,因此您可能无法观察到最近写入的值
如果您不想使用 Thread.Join
,只需添加对 Thread.Sleep
的调用,例如Thread.Sleep(5000)
- 极有可能 所有线程在那之后都会完成。然后你可以使用:
lock (syncObject)
{
Console.WriteLine(Counter);
}
简而言之,lock
没有任何问题,尽管您最好使用 Interlocked.Increment
。
我正在尝试在 FOR 循环中使用两个不同的线程来推进静态 (int) 计数器,因此如果循环是 运行s 10 倍我 (should) 得到计数器=20。出于某种原因,我每次 运行 循环 (19,20,21) 时都会得到不同的值,即使我使用 LOCK 访问该计数器,(控制台中的代码 运行s):
public static int Counter = 0;
static object syncObject = new object();
static void Main(string[] args)
{
int ForLength = 10;
Thread FirstThread, SecondThread;
for (int i = 0; i <= ForLength; i++)
{
FirstThread = new Thread(RaiseCounter);
FirstThread.IsBackground = false;
SecondThread = new Thread(RaiseCounter);
SecondThread.IsBackground = false;
FirstThread.Start();
SecondThread.Start();
//Console.WriteLine(Counter);
}
Console.WriteLine(Counter);
Console.ReadLine();
}
public static void RaiseCounter ()
{
lock (syncObject)
{
Counter++;
}
}
你遇到了三个问题:
你实际上 运行 循环 11 次:
for (int i = 0; i <= ForLength; i++) // i=0 to i=10 *inclusive*
您没有加入线程(或休眠),因此在您编写输出时其中一些线程可能尚未完成
当您在主线程中读取
Counter
时,您没有在syncObject
上进行同步,因此您可能无法观察到最近写入的值
如果您不想使用 Thread.Join
,只需添加对 Thread.Sleep
的调用,例如Thread.Sleep(5000)
- 极有可能 所有线程在那之后都会完成。然后你可以使用:
lock (syncObject)
{
Console.WriteLine(Counter);
}
简而言之,lock
没有任何问题,尽管您最好使用 Interlocked.Increment
。