在简单地分配变量时,我需要使用锁吗
本文关键字:简单 分配 变量 | 更新日期: 2023-09-27 18:20:50
当多线程时,我知道如果要向列表中添加和项等操作,我需要锁定变量,否则会出现跨线程异常。但是,在分配变量时,我需要锁定它们吗?我不介意线程是否获得该变量的旧实例——我只是不希望它出错。下面是我的意思的一个例子:
public void Run()
{
var thread1 = new Thread(new ThreadStart(Test));
var thread2 = new Thread(new ThreadStart(Test));
thread1.Start();
thread2.Start();
}
private static int _test;
private void Test()
{
while (true)
{
_test += 1;
}
}
如果您只是分配一个int
,那么不是。但在这里,您不仅仅是分配。你在增加。所以你需要某种同步。
在您想要增量时,使用Interlocked.increment:
Interlocked.Increment(ref _test);
运行代码应该会给出答案。。。将结果写入屏幕并运行,而不是while(true)
写入for(i=1;1<1e6;i++)
你会看到它加起来不是2e6,而是大约1.2e6。所以,是的,如果你想出去,你需要上锁。
不要只是假设,之后总是测试和断言。
您必须记住,线程也可能正在查看过时的副本,通过锁定确保您正在查看的变量的版本正在刷新
当我刚开始编码时,我认为也许我不需要变量的最新副本,我会陷入无限循环,因为我认为变量最终会更新,但如果变量被缓存,它就永远不会更新
我包括了一些带有简短描述的例子,不用担心线程的启动方式,这与无关
private static bool _continueLoop = true;
private static readonly object _continueLoopLock = new object();
private static void StopLoop()
{
lock(_continueLoopLock)
_continueLoop = false;
}
private static void ThreadALoopWillGetStales()
{
while(_continueLoop)
{
//do stuff
//this is not guaranteed to end
}
}
private static void ThreadALoopEventuallyCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
doContinue = _continueLoop;
if(!doContinue)
break;
//do stuff
//this will sometimes result in a stale value
//but will eventually be correct
}
}
private static void ThreadALoopAlwaysCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
if(!_continueLoop)
break;
//do stuff
//this will always be correct
}
}
private static void ThreadALoopPossibleDeadlocked()
{
lock(_continueLoopLock)
while(_continueLoop)
{
//if you only modify "_continueLoop"
//after Acquiring "_continueLoopLock"
//this will cause a deadlock
}
}
private static void StartThreadALoop()
{
ThreadPool.QueueUserWorkItem ((o)=>{ThreadALoopWillGetStales();});
}
private static void StartEndTheLoop()
{
ThreadPool.QueueUserWorkItem((o)=>
{
//do stuff
StopLoop();
});
}
public static void Main(string[] args)
{
StartThreadALoop();
StartEndTheLoop();
}
当您启动循环时,有可能会继续获得变量的陈旧副本,这就是为什么您在访问跨多个线程的时需要某种同步的原因