文档章节

Parallel并行之乱用

drv
 drv
发布于 2016/12/28 11:25
字数 980
阅读 4
收藏 0

  关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是。

  我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说,愿意往下看的可以看看因果,不愿意看的,也算咱给大家提个醒吧。

  结论就是,大家在做单元测试用例的时候一定要用心,这篇随笔是要检讨并警醒下自己并与大家共勉。

  据一些我不记得名字的国外权威专家,据说是测试大师级人物研究,测试用例的出现的错误并不比被测试的代码少,我相信大多数人会和我类似,在写代码的时候小心翼翼,但是为代码编写单元测试及用例的时候往往注意力下意识的不那么集中,今天就是这么个情况。可能是缺乏锻炼(我天天打太极拳的。。。)的原因,连续几个晚上由于学习原因睡的比较晚,今天就比较困,然后干了件点题的事。

  我写了一个对象ID生成器,以时间戳和顺序号组合,虽然不支持集群,但是目前情况下足够了,然后因为复制数据库的同事坚决不同意将主键的int类型改掉,那怕改成bigint都不同意。。。跑题了。总之,各种限制的情况下出了这么个东西:

  //不能再集群情况下使用
    public class IDGenerator
    {
     private static double _seconds = 0; private static int _sequenceIndex = 0; private static object _lock = new object();
     private static ReaderWriterLockSlim writerLock = new ReaderWriterLockSlim();
private static IDGenerator _instance; private IDGenerator() { } public static int NewID { get { int newID = IDGenerator.Instance.CreateNewID(); return newID; } } private int CreateNewID() { string id; writerLock.EnterReadLock(); try { id = BuildIDAndUpdateSead(); } finally//保证退出锁 { writerLock.ExitReadLock(); } int newID = TypeParseHelper.GetIntValueByString(id); return newID; } private string BuildIDAndUpdateSead() { double seconds; bool isEqualSecondsCount; seconds = InterceptSecondsInTicks(); isEqualSecondsCount = seconds.Equals(_seconds); if (isEqualSecondsCount) {
         
bool isUpperBound = _sequenceIndex == 999; if (isUpperBound) { Thread.Sleep(1000); _sequenceIndex = 0; _seconds++; }
          else
          {
  Interlocked.Increment(ref _sequenceIndex);
          }
}
else
 { _seconds = seconds; } string id = _seconds.ToString() + _sequenceIndex.ToString().PadLeft(3, '0'); return id; } private double InterceptSecondsInTicks() { DateTime currentDate = DateTime.Now; long elapsedTicks = (currentDate.Ticks - ConstantGather.BEGIN_STANDARD_TICKS); TimeSpan elapsedSpan = new TimeSpan(elapsedTicks); double seconds = Math.Floor(elapsedSpan.TotalSeconds); return seconds; } private static IDGenerator Instance { get { if (_instance != null) { return _instance; } lock (_lock) { if (_instance == null) { _instance = new IDGenerator(); } }  return _instance; } } }

  做完了,当然要写点单元测试测试一下,就先写了个同步的,然后写了个异步的,然后写了个并发的

public List<int> GenerateRequisitionIDs()
        {            
            TaskFactory taskFactory = new TaskFactory();
            Task<int>[] tasks = new Task<int>[] { 
                taskFactory.StartNew(() => GenerateRequisitionID()),
                taskFactory.StartNew(() => GenerateRequisitionID()),
                taskFactory.StartNew(() => GenerateRequisitionID()) };   var query = tasks.Where(t => !t.Result.Equals(0))
                 .Select(t => t.Result);
            return query.ToList();
        }

  高潮来了,然后我在单元测试里顺手写了个并行的。。。

Parallel.For(0, actual, c =>
            {
                int id = target.GenerateRequisitionID();
                list.AddLast(id);
            });

  测试结果就不停得出错,我费了很大功夫定位到了出错的位置。。。

string idStr = _seconds.ToString() + "-" + _sequenceIndex.ToString().PadLeft(3, '0');

  这一句是我写了一堆定位错误的代码中的一句,发现了个奇怪的现象,这个字符串赋值后,两边居然是不一样的,而且这一句在排它锁里。。。

  并行的用法应该是将一对任务,平均分开,各自做各自的,互相不影响,问题就在于我这生成器是个单例。。。

  作为一个敬业的标题党,并发和并行的区别我就不说了,反正连百度都知道的事。。。  

  最后说一句,单元测试要认真,单元测试的代码哪怕随便玩的也要组织好,不要乱放,不要完全不着边的都测,正常业务里是不会有并行生成ID的场景的,这个测试没有意义,而且,如果看了生成器的代码会发现,由于int32本身的长度问题,我限定了一秒最多能生成999个ID,我需要测的其实不是并行问题,太晚了,思维比较跳跃,就这么着吧,下次长点记性就好了,以上。

 

© 著作权归作者所有

下一篇: CSS画图
drv

drv

粉丝 2
博文 57
码字总数 75382
作品 0
东城
架构师
私信 提问
PostgreSQL官方并行更新时间表

2013年10月,创建了两个主要的基础架构:Dynamic Background Workers 和 Dynamic Shared Memory。 2014年11月,Amit Kapila发布了并行顺序扫描(parallel sequential scan)的草案补丁,Rob...

悟道之客
2018/10/30
0
0
PgSQL · 特性分析 · PostgreSQL 9.6 让多核并行起来

背景 经过多年的酝酿(从支持work process到支持动态fork共享内存,再到内核层面支持并行计算),PostgreSQL 的多核并行计算功能终于在2016年发布的9.6版本中正式上线,为PG的scale up能力再...

阿里云RDS-数据库内核组
2016/11/08
0
0
PostgreSQL 11 preview - 并行计算 增强 汇总

标签 PostgreSQL , 并行 , 增强 , 11 背景 PostgreSQL 11 并行计算能力的增强。 E.1.3.1.2. Parallel Queries Allow btree indexes to be built in parallel (Peter Geoghegan, Rushabh Lath......

德哥
2018/07/28
0
0
并行复制(MTS:enhanced Multi-threaded slave)

5.7.2 支持单库增强型多线程slave(多个sql work线程),mariadb 10.0.5支持 原理 slave利用事务组提交的特性(To provide parallel execution of transactions in the same schema, MariaDB 10......

AnthonyYau
2016/04/20
422
0
oracle使用并行踩过的坑

一、并行机制的简述 并行处理的机制实际上就是把一个要扫描的数据集分成很多小数据集,Oracle会根据初始化参数 PARALLELMINSERVERS=n的值启动几个并行服务进程同时处理这些小数据集,最后将这...

朱wei
2017/07/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
43分钟前
6
0
太全了|万字详解Docker架构原理、功能及使用

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpa...

Java技术剑
44分钟前
9
0
Wifiphisher —— 非常非常非常流氓的 WIFI 网络钓鱼框架

编者注:这是一个非常流氓的 WIFI 网络钓鱼工具,甚至可能是非法的工具(取决于你的使用场景)。在没有事先获得许可的情况下使用 Wifiphisher 攻击基础网络设施将被视为非法活动。使用时请遵...

红薯
今天
49
1
MongoDB 4 on CentOS 7安装指南

本教程为CentOS x86_64 7.x操作系统下,MongoDB Community x86_64 4.2(GA)安装指南。 安装方式一:yum repo在线安装 [此方式较为简单,官方推荐] Step1:新建MongDB社区版Yum镜像源。 # vim ...

王焱君
今天
7
0
go-micro 入门教程1.搭建 go-micro环境

微服务的本质是让专业的人做专业的事情,做出更好的东西。 golang具备高并发,静态编译等特性,在性能、安全等方面具备非常大的优势。go-micro是基于golang的微服务编程框架,go-micro操作简单...

非正式解决方案
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部