在处理多线程应用程序时,我曾经遇到过需要为静态字段赋值的场景。我想在所有其余的线程中使用静态字段的最新值。
代码如下所示:
Main()方法:
for (var i = 1; i <= 50; i++)
{
ProcessEmployee processEmployee = new ProcessEmployee();
Thread thread = new Thread(processEmployee.Process);
thread.Start(i);
}
public class ProcessEmployee
{
public void Process(object s)
{
// Sometimes I get value 0 even if the value set to 1 by other thread.
// Want to resolve this issue.
if (StaticContainer.LastValue == 0)
{
Console.WriteLine("Last value is 0");
}
if (Convert.ToInt32(s) == 5)
{
StaticContainer.LastValue = 1;
Console.WriteLine("Last Value is set to 1");
}
// Expectation: want to get last value = 1 in all rest of the threads.
Console.WriteLine(StaticContainer.LastValue);
}
}
public static class StaticContainer
{
private static int lastValue = 0;
public static int LastValue
{
get
{
return lastValue;
}
set
{
lastValue = value;
}
}
}
问题:
基本上,我想知道一旦我通过任何线程将特定值设置为静态字段,我想得到相同的值(由另一个{设置的最新值) {1}})其余的thread
始终。
请给我任何想法。
提前致谢!
答案 0 :(得分:4)
基本上,我想知道,一旦我通过任何线程将特定值设置为静态字段,我希望总是在其余线程中获得相同的值(由另一个线程设置的最新值)。
听起来你基本上没有记忆障碍。你可以使用明确的障碍但没有锁定来解决这个问题 - 或者你可以选择强力锁定方法,或者你可以使用Interlocked
:
private static int lastValue;
public int LastValue
{
// This won't actually change the value - basically if the value *was* 0,
// it gets set to 0 (no change). If the value *wasn't* 0, it doesn't get
// changed either.
get { return Interlocked.CompareExchange(ref lastValue, 0, 0); }
// This will definitely change the value - we ignore the return value, because
// we don't need it.
set { Interlocked.Exchange(ref lastValue, value); }
}
你可以按照评论中newStackExchangeInstance的建议使用volatile
- 但我从未确定我完全理解完全它意味着什么,我强烈地怀疑它并不意味着大多数人认为它意味着什么,或者确实是MSDN文档所说的。您可能需要阅读Joe Duffy's blog post on it(and this one too)了解更多背景信息。
答案 1 :(得分:1)
如果两个不同的线程可以访问相同的字段/变量,并且其中至少有一个将写入,则需要使用某种锁定。对于原始类型,请使用Interlocked
类。