2

当多线程时,我知道我需要锁定变量,例如添加和项目到列表等,否则我会得到一个跨线程异常。但是在分配变量时我需要锁定它们吗?我不介意线程是否获取变量的旧实例 - 我只是不希望它出错。这是我的意思的一个例子:

    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;
        }
    }
4

3 回答 3

5

如果你只是分配一个int,那么没有。但在这里你不只是分配。你在增加。所以你需要某种同步。

在你想增加,使用Interlocked.Increment

Interlocked.Increment(ref _test);
于 2013-07-03T18:48:27.623 回答
0

You have to remember the thread could also be looking at a stale copy, by locking you assure that the version of the variable you are looking at is being refreshed

When I first started coding and thought that maybe I don't need the freshest copy of the variable I would get stuck in infinite loops because I assume the variable would be updated eventually, but if the variable was cached then it would never update

I included examples with brief descriptions, don't worry about the way the thread is started, that is not relevant

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();
}

when you start the loop there is a chance that you will continue to get a stale copy of the variable, that is why you do need some sort of synchronization when accessing a across multiple threads

于 2013-07-03T18:45:44.473 回答
0

运行代码应该会给你答案......而不是while(true)write for(i=1;1<1e6;i++),将结果写入屏幕并运行它。

你会看到它加起来不等于 2e6,而是大约 1.2e6。所以是的,如果你想退出 2e6,你需要锁定。

不要只是假设,之后总是测试和断言。

于 2013-07-03T18:53:30.047 回答