C# 在不同的线程上使用捕获的变量时是否需要锁定 public void GetData() { var locker=新对象(); var WAERER=新手动重置事件(false); 列表数据=null; 变量线程=新线程(()=> { 锁(储物柜) { data=GatherData(); } 服务员:Set(); }); thread.Start(); 服务员,等一等; 锁(储物柜) { 返回数据; } }

C# 在不同的线程上使用捕获的变量时是否需要锁定 public void GetData() { var locker=新对象(); var WAERER=新手动重置事件(false); 列表数据=null; 变量线程=新线程(()=> { 锁(储物柜) { data=GatherData(); } 服务员:Set(); }); thread.Start(); 服务员,等一等; 锁(储物柜) { 返回数据; } },c#,multithreading,C#,Multithreading,在这个代码中,锁是无用的吗?为什么?在这里设置记忆障碍很重要。即使您知道读操作将发生在写操作之后,如果没有障碍,那么读操作将被允许读取缓存的值,或者写操作可能不需要从缓存传播其值 也就是说,您正在使用的ManualResetEvent将在等待时引入内存屏障,因此您不需要显式地添加另一个。锁也会引入一个屏障,但由于您已经有了一个屏障,因此在这种情况下它是多余的 说到这里,值得指出的是,创建一个新线程只是坐在那里等待它是毫无意义的。您也可以直接在原始线程中运行代码,除非您忽略了让该线程在等待第二个线

在这个代码中,锁是无用的吗?为什么?

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

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

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


假设您确实需要第二个线程开始,您应该在这里真正考虑使用
任务
,因为它将代表您处理任务之间传递的结果的所有同步。

由于您在
WaitOne
中阻止调用
GetData
的线程,因此没有理由使用线程。由于代码中没有同时访问
数据
,因此不需要锁定。实际上,我使用线程是为了强制GatherData在STA线程中运行,但在您的代码
SetApartmentState
方法中看不到任何地方。顺便问一下:你为什么需要这个?这算是什么?有什么理由对试图回答你问题的人无礼吗?我只是需要进一步解释这段胡说八道的代码。对不起,我不想无礼。我只是想让问题尽可能精确,但似乎我失败了。
    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;
        }
    }