热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在HashSet<T>中包含线程安全

如何解决《在HashSet<T>中包含线程安全》经验,为你挑选了1个好方法。

看一下.NET源代码Contains中的HashSet类代码,我找不到任何Contains线程安全的原因?

HashSet提前加载了一个值,然后检查Contains多线程.AsParallel()环.

这有什么理由不安全吗?ConcurrentDictionary当我实际上不需要存储值时,我不愿意使用.



1> xanatos..:

通常(通常)仅用于读取的集合是"非正式"线程安全的(.NET中没有我知道在读取期间自行修改的集合).有一些警告:

本身不能成为项目线程安全的(但有HashSet这个问题应尽量减少,因为你不能从中提取项目.仍然是GetHashCode()Equals()必须是线程安全的.如果,例如,他们访问所加载懒对象按需,它们可能不是线程安全的,或者它们可能缓存/记忆一些数据以加速后续操作)

您必须确保在最后一次写入之后有一个Thread.MemoryBarrier()(在与写入相同的线程中完成)或等效的,否则在另一个线程上读取可能会读取不完整的数据

你必须确保在每个线程(不同于你写的那个)中,在第一次读取之前有一个Thread.MemoryBarrier().请注意,如果HashSet在创建/启动其他线程之前已经"准备好"(最后使用Thread.MemoryBarrier()),那么Thread.MemoryBarrier()就没有必要了,因为线程不能过时读取内存(因为他们不存在).各种操作导致隐含Thread.MemoryBarrier().例如,如果在HashSet填充之前创建的线程,输入a Wait()并且un-WaitedHashSet填充之后(加上它Thread.MemoryBarrier()),则退出a Wait()会导致隐式Thread.MemoryBarrier()

使用memoization/lazy loading /任何你想要调用它的类的简单示例可以打破线程的安全性.

public class MyClass
{
    private long value2;

    public int Value1 { get; set; }

    // Value2 is lazily loaded in a very primitive
    // way (note that Lazy *can* be used thread-safely!)
    public long Value2
    {
        get
        {
            if (value2 == 0)
            {
                // value2 is a long. If the .NET is running at 32 bits,
                // the assignment of a long (64 bits) isn't atomic :)
                value2 = LoadFromServer();

                // If thread1 checks and see value2 == 0 and loads it,
                // and then begin writing value2 = (value), but after
                // writing the first 32 bits of value2 we have that
                // thread2 reads value2, then thread2 will read an
                // "incomplete" data. If this "incomplete" data is == 0
                // then a second LoadFromServer() will be done. If the
                // operation was repeatable then there won't be any 
                // problem (other than time wasted). But if the 
                // operation isn't repeatable, or if the incomplete 
                // data that is read is != 0, then there will be a
                // problem (for example an exception if the operation 
                // wasn't repeatable, or different data if the operation
                // wasn't deterministic, or incomplete data if the read
                // was != 0)
            }

            return value2;
        }
    }

    private long LoadFromServer()
    {
        // This is a slow operation that justifies a lazy property
        return 1; 
    }

    public override int GetHashCode()
    {
        // The GetHashCode doesn't use Value2, because it
        // wants to be fast
        return Value1;
    }

    public override bool Equals(object obj)
    {
        MyClass obj2 = obj as MyClass;

        if (obj2 == null)
        {
            return false;
        }

        // The equality operator uses Value2, because it
        // wants to be correct.
        // Note that probably the HashSet doesn't need to
        // use the Equals method on Add, if there are no
        // other objects with the same GetHashCode
        // (and surely, if the HashSet is empty and you Add a
        // single object, that object won't be compared with
        // anything, because there isn't anything to compare
        // it with! :-) )

        // Clearly the Equals is used by the Contains method
        // of the HashSet
        return Value1 == obj2.Value1 && Value2 == obj2.Value2;
    }
}


推荐阅读
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • C#多线程解决界面卡死问题的完美解决方案
    当界面需要在程序运行中不断更新数据时,使用多线程可以解决界面卡死的问题。一个主线程创建界面,使用一个子线程执行程序并更新主界面,可以避免卡死现象。本文分享了一个例子,供大家参考。 ... [详细]
  • 如何解决《JavaHashSet包含无法正常工作的函数》经验,为你挑选了1个好方法。 ... [详细]
  • Java:HashSet与HashMap
    如何解决《Java:HashSet与HashMap》经验,为你挑选了2个好方法。 ... [详细]
  • HashSet and HashMap
    HashSetandHashMap总体介绍之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashS ... [详细]
  • HiIhaveaHashSetlikethefollowinginaclasscalledMemory:嗨,我在一个名为Memory的类中有如下的HashSet:Set& ... [详细]
  • TheHashSetclasshasanadd(Objecto)method,whichisnotinheritedfromanotherclass.TheJavado ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
author-avatar
jack1881的天空_925
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有