本系列学习在.NET中的并发并行编程模式,实战技巧

内容目录

.NET不可变集合.NET并发集合函数式数据结构设计一个不可变类

作为程序员经常遇到产品上线后出现各种莫名其妙的问题,在我本地是好好的啊,也成为程序员面对未知问题的第一反应。这种不容易复现的问题,无非就是硬件不一致和软件不一致,更多的问题出在软件环境上,用户量、 并发这种测试容易遗漏的点。

为了保证编写的代码在不同的环境中出现一致的行为结果,通常就要利用不可变的数据结构。数据一旦创建后就不能修改其本身,修改后会产生新的数据。

.NET不可变集合

在.NET4.5引入不可变集合,在命名空间System.Collecttions.Immutable中。(注意这个类库不是.net核心类库,需要从nuget上安装)。不可变的集合结构每次修改数据后都会生成新的集合。像String类型一样,对它Substring,Replace都会生成新的字符串。

  1. //可以将普通可变集合直接转为不可变集合
    var dic = new Dictionary<int, int>().ToImmutableDictionary();
    //直接创建不可变集合
    var list = ImmutableList.Create<int>(); 
                list = list.Add(1); 
                list = list.Add(2);
                list = list.Add(3);  

由于集合不可变,也就保证了多线程的安全。直接将集合丢给每个线程,原始集合不会变化。

.NET并发集合

还有一种线程安全集合在System.Collections.Concurrent中,在多线程环境中建议使用此类集合。Concurrent集合是可变集合,但提供了细粒度和无锁模式来提高多线程应用程序的性能和可扩展性。像ConcurrentDictionary字典,除了像传统字典Dictionary使用,还提供了很多兼容并发的方法,如AddOrUpdate或GetOrAdd等。如果不使用并发集合,在多线程环境中我们需要设置锁来保证数据的一致性。

函数式数据结构

可持久化数据结构也称之为函数式数据结构。可持久化意味着数据结构是不可变的,修改只会返回修改后的新数据结构。(这里数据持久化和IO持久化区分)。大多数命令式数据结构都是短暂的,修改就破坏其结构。如Dictionary,List,Queue等。

不可变性可能会带来一定的损耗,每次修改都会生成新的数据数据结构。但在托管编程语言中,如C# 和Java中,已经做了足够多的优化,且在多核时代,基本可以忽略性能的影响。

以链表数据结构为例说明托管语言在共享数据结构上做的优化

不可变的数据集合,每次修改后,不是完整拷贝原集合,比如集合中追加一项,只会修改引用指向的位置,共享剩余其他结构。

设计一个不可变类

C#有readonly和const两个关键字,还记得他们的区别和用处吗。const静态常量,编译时被解析,通过类访问。readonly动态常量,可延迟到构造函数中初始化,通过类实例访问。

  1. public class Person
    {
        public const string Contry = "中国";
        public string Name { get; }
        public readonly Address Address;
        public Person(string name, Address address)
        {
            this.Name = name;
            this.Address = address;
        }
    }

    public class Address
    {
        public string Street;
        public Address(string street)
        {
            this.Street = street;
        }
    }

代码示例中,控制了Person的Address地址是不能被修改的,但它的底层字段Street仍然可以被修改。这就会导致person.Address.Street="M78星云"这样的行为,所以这就是浅不可变。微软考虑到不可变编程的重要性,随后又在C#6.0又引入了自动属性的概念,可以轻松的创建一个不可变类。像示例中的public string Name { get; }这样。

to be contiued!
下集:数据并行

.NET并发编程-数据结构不可变性的更多相关文章

  1. 2019年BAT面试通关宝典:数据结构+JVM+并发编程+分布式...

    前言 金三银四俗称跳槽黄金季,很多同学都想趁着这段时间拿高薪,去更牛逼的公司工作,认识更多大牛,提升自己的职场竞争力. 那怎样才能通过BAT面试官的考核?怎样成为一名Offer收割机? 收割Offer ...

  2. [书籍翻译] 《JavaScript并发编程》第六章 实用的并发

    本文是我翻译<JavaScript Concurrency>书籍的第六章 实用的并发,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript ...

  3. java并发编程 --并发问题的根源及主要解决方法

    目录 并发问题的根源在哪 缓存导致的可见性 线程切换带来的原子性 编译器优化带来的有序性 主要解决办法 避免共享 Immutability(不变性) 管程及其他工具 并发问题的根源在哪 首先,我们要知 ...

  4. .NET并发编程-函数式编程

    本系列学习在.NET中的并发并行编程模式,实战技巧 函数式编程 和面向过程编程POP(procedure oriented Programming)面向对象编程OOP(object oriented ...

  5. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  6. 【Java并发编程实战】-----“J.U.C”:Exchanger

    前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...

  7. 【转】Java并发编程注意事项

    保证线程安全的三种方法: 不要跨线程访问共享变量 使共享变量是final类型的 将共享变量的操作加上同步 一开始就将类设计成线程安全的, 比在后期重新修复它,更容易. 编写多线程程序, 首先保证它是正 ...

  8. Java并发编程:Timer和TimerTask(转载)

    Java并发编程:Timer和TimerTask(转载) 下面内容转载自: http://blog.csdn.net/xieyuooo/article/details/8607220 其实就Timer ...

  9. Java并发编程:并发容器之ConcurrentHashMap(转载)

    Java并发编程:并发容器之ConcurrentHashMap(转载) 下面这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concu ...

随机推荐

  1. IOC技术在前端项目中的应用

    目录 背景 什么是IOC 如何实现一个IOC 第一步:实现一个容器 第二步:用好装饰器 第三步:使用容器 扩展和展望 最后 背景 前端发展至今已经过去30余年,前端应用领域在不断壮大的过程中,也变得越 ...

  2. SpringBoot 自动配置:Spring Data JPA

    前言 不知道从啥时候开始项目上就一直用MyBatis,其实我个人更新JPA些,因为JPA看起来OO的思想更强烈些,所以这才最近把JPA拿出来再看一看,使用起来也很简单,除了定义Entity实体外,声明 ...

  3. 树莓派zero 使用usb串口连接

    使用minicom连接bash$ lsusbBus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubBus 001 Device 0 ...

  4. MySQL主从复制配置部署

    配置前准备:安装MySQL   MySQL在centOS上的安装传送门: 1.集群规划 hadoop105 hadoop106 hadoop107 MySQL(master) MySQL(slave) ...

  5. oblet

      oblet - The Go Programming Language https://golang.google.cn/search?q=oblet // put enqueues a poin ...

  6. BI学习向导文章

    BI的学习笔记: BIWORK的博客:http://www.cnblogs.com/biwork/p/3328879.html 邀月工作室博客 :http://www.cnblogs.com/down ...

  7. RPM 和YUM总结

    RPM RPM命名: 安装 rpm -ihv 其他常用的选项: 1. 重新安装 --replacepkgs (或者 --force ) 2. 不考虑依赖 --nodeps (不推荐) 升级: 查询: ...

  8. LOJ10199轻拍牛头

    题目描述 原题来自:USACO 2008 Dec. Silver 今天是 Bessie 的生日,并且现在是聚会的游戏时间.Bessie 让编号为 1~N 的 N 头奶牛围成一个圈坐(所以除了最后一头牛 ...

  9. 静默安装Oracle也没那么恐怖

    几种必须静默安装的情况 服务器为了减少资源占用,没安装图形组件 不能进入机房,只能远程SSH 想炫(Z)耀(B),静默安装显得有技术含量 磁盘分区要求 如没有特别要求,装机时可按如下分区比较好管理 / ...

  10. jQuery——通过Ajax发送数据

    Ajax(Asynchronous JavaScript and XML,异步JavaScript和XML),一个Ajax解决方案涉及如下技术: JavaScript:处理与用户及其他浏览器相关事件的 ...