Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 仅在修改vs整个方法时锁定_C#_Multithreading - Fatal编程技术网

C# 仅在修改vs整个方法时锁定

C# 仅在修改vs整个方法时锁定,c#,multithreading,C#,Multithreading,什么时候应该使用锁?仅在修改数据或访问数据时 public class Test { static Dictionary<string, object> someList = new Dictionary<string, object>(); static object syncLock = new object(); public static object GetValue(string name) { if (someLi

什么时候应该使用锁?仅在修改数据或访问数据时

public class Test {
    static Dictionary<string, object> someList = new Dictionary<string, object>();

    static object syncLock = new object();

    public static object GetValue(string name) {
        if (someList.ContainsKey(name)) {
            return someList[name];
        } else {
            lock(syncLock) {
                object someValue = GetValueFromSomeWhere(name);
                someList.Add(name, someValue);
            }
        }
    }
}
公共类测试{
静态字典someList=新字典();
静态对象同步锁=新对象();
公共静态对象GetValue(字符串名称){
if(someList.ContainsKey(name)){
返回someList[名称];
}否则{
锁定(同步锁定){
object someValue=GetValueFrom某地(名称);
添加(名称,someValue);
}
}
}
}

是否应该在整个块的周围有一个锁,或者只将其添加到实际修改中就可以了?我的理解是,仍然可能存在一些竞争条件,其中一个调用可能没有找到它并开始添加它,而紧接着的另一个调用也可能遇到相同的情况,但我不确定。锁定仍然很混乱。我没有遇到任何问题与上述类似的代码,但我可能只是幸运到目前为止。以上任何帮助以及如何/何时锁定对象的良好资源都将受到欢迎。

您在读取时也必须锁定,否则您可能会获得不可靠的数据,甚至在并发修改实际更改目标数据结构时出现异常

在上述情况下,您需要确保多个线程不会同时尝试添加该值,因此在检查该值是否已存在时,您至少需要一个读锁。否则,多个线程可能会决定添加,发现值不存在(因为此检查未锁定),然后所有线程依次尝试添加(在获得锁定后)

如果您有很多读操作,而只有很少的写操作,则可以使用。在上面的代码中,一旦您决定需要添加读锁,您将获得读锁来执行检查并升级到写锁。在大多数情况下,只需要一个读锁(它允许读线程仍然并行运行)

有可用的.NET4锁定原语的摘要。在深入研究多线程代码之前,一定要了解这一点。选择正确的锁定机制可以产生巨大的性能差异


到目前为止,您是幸运的,这是并发错误的一个常见特征。如果不进行有针对性的负载测试,它们通常很难复制,这意味着正确的设计(当然还有详尽的测试)对于避免令人尴尬和困惑的生产错误至关重要。

在检查
name
是否存在之前锁定整个块。否则,理论上,另一个线程可以在检查和添加它的代码之间添加它


实际上,在执行Add时锁定实际上什么都不做。这样做只是防止另一个线程同时添加某些内容。但是,由于另一个线程已经决定要进行添加,所以只要释放锁,它就会尝试进行添加。

如果一个资源只能由多个线程访问,则不需要任何锁


如果一个资源可以被多个线程访问并且可以修改,那么所有的访问/修改都需要同步。在您的示例中,如果
getvaluefromwhere
需要很长时间才能返回,则可以使用
name
中的相同值进行第二次调用,但该值尚未存储在
字典中

ReaderWriterLock或苗条版(如果低于4.0)

您将获得读取的读卡器锁(允许并发读取),并在写入时将锁升级为写入器锁(一次只允许一次写入,并将阻止所有读取,直到完成,以及并发写入线程)

确保按此模式释放锁,以避免死锁:

            void Write(object[] args) 
            {


                   this.ReaderWriterLock.AquireWriteLock(TimeOut.Infinite);

                    try 
                    {
                      this.myData.Write(args);

                    }
                    catch(Exception ex) 
                    {

                    }
                    finally 
                    {

                        this.ReaderWriterLock.RelaseWriterLock();
                    }

            }

另一个过程?术语很重要。所有可用的锁定机制都有很好的链接。我只听说过
lock
。祝你好运-如果你能掌握这方面的知识,你将成为少数为多核开发做好准备的开发人员。