.net core 多线程下使用 Random 会出现的bug

先看原文:

Working with System.Random and threads safely in .NET Core and .NET Framework

https://andrewlock.net/building-a-thread-safe-random-implementation-for-dotnet-framework/

我的结论:

.net 6 之前,如果习惯构建了一个静态的 Random 对象,然后业务代码里直接使用 random.Next() 方法,多线程竞争下,会有一定概率返回0。

.net 6 时,修正了这个默认创建时的多线程存在的bug。但又没完全解决。如果这个公共的 Random 方法初始化的适合使用了自定义随机种子,则还是会存在多线程竞争下出现返回0情况。

原文提供了在 .net 6 之前版本的一些解决办法,我的建议是使用 random.Next(1, 10000) 这样的方法生成随机数。

原文测试用代码片段[改]:


using System;
using System.Linq;
using System.Threading.Tasks; public class Program { public static void Main() {
// This isn't safe, don't do it
Random rng = new Random(); // create a shared Random instance
Parallel.For(0, 10, x => // run in parallel
{
var numbers = new int[10_000];
for (int i = 0; i < numbers.Length; ++i)
{
numbers[i] = rng.Next(); // Fetch 10,000 random numbers, to trigger the thread-safety issues
} var numZeros = numbers.Count(x => x == 0); // how many issues were there?
var avg = numbers.Average();
Console.WriteLine($"Received {numZeros} zeroes avg:{avg} {numbers[0]}");
});
}
}

当然好奇的脚步不止于此,为什么文章说的,大部分人习惯直接调用 .Next() 方法,而不是 .Next(min,max) 这样的方法呢?

我姑且认为是性能问题,于是增加了一个性能测试代码片段,用于生成 (1,100)区间内的随机数:

    public class RandomT
{
System.Random random1 = new System.Random(1);
System.Random random2 = new System.Random(1); System.Random random11 = new System.Random();
System.Random random22 = new System.Random(); [Benchmark]
public int RandomSeedByRange() => random1.Next(1, 100); [Benchmark]
public int RandomSeedByMod() => random2.Next() % 100 + 1; [Benchmark]
public int RandomDefaultByRange() => random11.Next(1, 100); [Benchmark]
public int RandomDefaultByMod() => random22.Next() % 100 + 1;
}

BenchmarkDotNet=v0.13.2, OS=ubuntu 20.04
Intel Xeon Gold 6133 CPU 2.50GHz, 1 CPU, 2 logical and 2 physical cores
.NET SDK=6.0.200
[Host] : .NET 6.0.2 (6.0.222.6406), X64 RyuJIT AVX2
DefaultJob : .NET 6.0.2 (6.0.222.6406), X64 RyuJIT AVX2
Method Mean Error StdDev
RandomSeedByRange 15.096 ns 0.1449 ns 0.1210 ns
RandomSeedByMod 14.759 ns 0.1298 ns 0.1014 ns
RandomDefaultByRange 9.310 ns 0.0702 ns 0.0548 ns
RandomDefaultByMod 4.925 ns 0.1387 ns 0.2393 ns

性能果然是直接使用 .Next() 最优。两者差距有一倍。

但是,指定随机种子后,两者就没有差距了,这就有点让人想不通了。

.net core 多线程下使用 Random 会出现bug的更多相关文章

  1. 一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext(LogicalSetData,LogicalGetData),含.net core的实现

    详情请参考原文:一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext

  2. Vector 是线程安全的,是不是在多线程下操作Vector就可以不用加Synchronized

    如标题一样,如果之前让我回答,我会说,是的,在多线程的环境下操作Vector,不需要加Synchronized. 但是我今天无意间看到一篇文章,我才发现我之前的想法是错误的,这篇文章的地址: http ...

  3. Java进阶专题(十五) 从电商系统角度研究多线程(下)

    前言 ​ 本章节继上章节继续梳理:线程相关的基础理论和工具.多线程程序下的性能调优和电商场景下多线程的使用. 多线程J·U·C ThreadLocal 概念 ​ ThreadLocal类并不是用来解决 ...

  4. 多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用

    本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSInvocationOperation.NSOperationQueue的使用,列举几个简单的例子. 默认情况下 ...

  5. python 类变量 在多线程下的共享与释放问题

    最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...

  6. Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask

    CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...

  7. Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger

    前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...

  8. 多线程下C#如何保证线程安全?

    多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题.所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是 ...

  9. 多线程下HashMap的死循环问题

    多线程下[HashMap]的问题: 1.多线程put操作后,get操作导致死循环.2.多线程put非NULL元素后,get操作得到NULL值.3.多线程put操作,导致元素丢失. 本次主要关注[Has ...

  10. ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 349人阅读 评论(0) 收藏

    问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...

随机推荐

  1. 【实用小技巧】RSA非对称加解密及XML&PEM格式互换方案

    ​ 最近因考虑接口安全问题,有实现给WEB API实现统一的参数鉴权功能,以防止请求参数被篡改或重复执行,参数鉴权方法基本与常见的鉴权思路相同,采用(timestamp+sign),而我为了防止tim ...

  2. Oracle ADG + Keepalived 切换演练

    客户的一套生产环境采用的架构是Oracle ADG + Keepalived,近期需要进行切换演练,要求我这边保障.ADG本身切换倒没啥可说的,但引入keepalived软件,就需要提前研究下这个架构 ...

  3. 如何在Windows端安装scala

    一.首先确保jdk安装成功   首先在安装之前,确保本地已经安装了JDK1.5以上的版本,在此安装的是1.8版本.并且已经设置了JAVA_HOME 环境变量及JDK的bin目录. 1.新建JAVA_H ...

  4. 计网学习笔记十 Internet Routing Protocols

    上一讲简单介绍了routing和两种最小路径算法的使用,这节课讲了两种算法是如何糅合进协议中来实现具体使用的. 这一讲内容有AS的介绍,以及IGP和BGP协议. Autonomous Systems ...

  5. NC53079 Forsaken喜欢数论

    题目链接 题目 题目描述 ​ Forsaken有一个有趣的数论函数.对于任意一个数 \(x\) , \(f(x)\) 会返回 \(x\) 的最小质因子.如果这个数没有最小质因子,那么就返回0. ​ 现 ...

  6. 【Android】使用 MediaMetadataRetriever 获取视频信息

    1 环境配置与初始化 ​ (1)申请权限 ​ 在 AndroidManifest.xml 中的 manifest 标签(application 同级标签)下添加外部存储读写权限,如下: <use ...

  7. Spring Boot学生信息管理系统项目实战-1.项目介绍

    1.获取源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.项目背景 刚开始自己帮教师朋友写的,核心是学生信息的导入导出功能.后来又扩展了几个模块. 水平一般能力有限,觉着有用的朋友可以拿去自 ...

  8. Oracle 高水位(HWM: High Water Mark) 说明

    一. 准备知识:ORACLE的逻辑存储管理. ORACLE在逻辑存储上分4个粒度: 表空间, 段, 区 和 块. 1.1 块: 是粒度最小的存储单位,现在标准的块大小是8K,ORACLE每一次I/O操 ...

  9. js根据输入字符长度自动调整textarea高度

    1.编写html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  10. EnumColorProfiles WcsGetDefaultColorProfile WcsSetDefaultColorProfile的使用

    #include <Windows.h> #include <Icm.h> #include <iostream> #include <string> ...