在不同的线程上使用捕获的变量时是否需要锁定

时间:2014-12-05 17:30:16

标签: c# multithreading

    public void GetData()
    {
        var locker = new object();
        var waiter = new ManualResetEvent(false);
        List<string> data = null;
        var thread= new Thread(() =>
        {
            lock (locker)
            {
                data = GatherData();
            }
            waiter.Set();
        });
        thread.Start();

        waiter.WaitOne();
        lock (locker)
        {
            return data;
        }
    }

在这段代码中,锁是否无用?为什么?

1 个答案:

答案 0 :(得分:0)

这里有一个记忆障碍很重要。即使你知道在写入之后会发生读取,如果没有障碍,那么读取将被允许读取缓存值,或者写入可能不需要从缓存传播其值。

也就是说,您正在使用的ManualResetEvent会在您等待时引入内存屏障,因此您无需显式添加另一个。 lock也会引入障碍,但由于你已经拥有了障碍,因此在这种情况下它是多余的。

说完这一切之后,值得指出的是创建一个新线程只是为了坐在那里等待它是毫无意义的。您也可以直接在原始线程中运行代码,除非您在等待第二个线程之前省略了使该线程执行其他操作的代码。

假设您确实需要第二个线程,那么您应该在此处使用Task,因为它将代表您处理在任务之间传递的结果的所有同步。