.net 是一本字典<;K、 V>;线程安全,用于同时读取和添加?

.net 是一本字典<;K、 V>;线程安全,用于同时读取和添加?,.net,dictionary,thread-safety,ajaxcontroltoolkit,.net,Dictionary,Thread Safety,Ajaxcontroltoolkit,这个问题涉及一个非常具体和常见的场景,其中字典用于多线程环境中项目的按需缓存。为了避免线程锁定,最好测试同步锁之外的现有缓存项,但是,如果我们随后必须添加一个项,那么它将被视为对字典的写入,因此我在stackoverflow上读到的大多数建议是,您需要锁定读取和写入,因为对add()的调用可能会改变字典的内部状态 但是,通过查看Microsoft的AjaxControlToolkit(scriptObjectBuilder类),该代码实际上在任何锁之外执行TryGet(),并且只执行将()新项添

这个问题涉及一个非常具体和常见的场景,其中字典用于多线程环境中项目的按需缓存。为了避免线程锁定,最好测试同步锁之外的现有缓存项,但是,如果我们随后必须添加一个项,那么它将被视为对字典的写入,因此我在stackoverflow上读到的大多数建议是,您需要锁定读取和写入,因为对add()的调用可能会改变字典的内部状态

但是,通过查看Microsoft的AjaxControlToolkit(scriptObjectBuilder类),该代码实际上在任何锁之外执行TryGet(),并且只执行将()新项添加到字典的锁。我可以看出,如果物品放入的桶在添加后从未改变,这可能是可能的,但我怀疑这是错误的,可能是错误的根源

谢谢

更新 根据.Net文档,我认为所描述的模式确实是错误的。然而,我想知道Dictionary的特定实现是否允许它,AjaxControlToolkit是否依赖它(这是可疑的)。在检查反射器中的代码时,我确信这确实是错误的,字典[Resisie]()方法重新定位桶的数量并移动桶项目,所以在TyGET()中的任何线程都可能在不稳定的数据上工作。 更新 已针对codeplex上的AjaxControlToolkit记录了一个缺陷。见:

苔丝·费兰德斯(Tess Ferrandez)对通用字典中的线程问题有一个自己的看法:

FindEntry方法遍历字典,试图找到键。如果多个线程同时执行此操作,特别是如果同时修改字典,则最终可能会在FindEntry中陷入无限循环,从而导致高CPU行为,进程可能会挂起


我想说这肯定是AjaxControlToolkit中的一个bug,并建议您在CodePlex上提出一个bug。它应该使用ReaderWriteLock(Slim)。

在一些调查之后回答我自己的问题:在检查Dictionary的代码时,我可以看到Dictionary.Resize()方法重新分配了用于存储数据的内部存储桶的数量,并重新分配存储桶内容,使项目基于其哈希代码位于正确的存储桶中。这样,在TyGET()中间的任何线程都会对不稳定的数据工作。p>
另一方面,Dictionary类的一种可能的低锁定方法可能是在Resize()方法周围放置一个锁。

您尝试过吗?客户端脚本通常是单线程的。标准警告适用。您是否尝试过自己编写测试线束?我很想看看这是否会导致任何问题。这是服务器端ajax代码。有线程同步,因为它使用静态字典缓存数据。@不退款:“尝试”对于多线程问题是非常不可靠的。谢谢。显然它已经在2007年被登录了,但我添加了一些输入。请参阅文章(上)中的链接,Rex M下面的答案更为正确,我在生产代码中遇到过这一点。同步整个进程,除非每个线程都是只读的。ReaderWriterLock[Slim]是合适的。