.net core 多线程下使用 Random 会出现bug
.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的更多相关文章
- 一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext(LogicalSetData,LogicalGetData),含.net core的实现
详情请参考原文:一个实现单线程/多线程下代码调用链中传递数据的处理类: CallContext
- Vector 是线程安全的,是不是在多线程下操作Vector就可以不用加Synchronized
如标题一样,如果之前让我回答,我会说,是的,在多线程的环境下操作Vector,不需要加Synchronized. 但是我今天无意间看到一篇文章,我才发现我之前的想法是错误的,这篇文章的地址: http ...
- Java进阶专题(十五) 从电商系统角度研究多线程(下)
前言 本章节继上章节继续梳理:线程相关的基础理论和工具.多线程程序下的性能调优和电商场景下多线程的使用. 多线程J·U·C ThreadLocal 概念 ThreadLocal类并不是用来解决 ...
- 多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用
本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSInvocationOperation.NSOperationQueue的使用,列举几个简单的例子. 默认情况下 ...
- python 类变量 在多线程下的共享与释放问题
最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...
- Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask
CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...
- Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger
前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲 ...
- 多线程下C#如何保证线程安全?
多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题.所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是 ...
- 多线程下HashMap的死循环问题
多线程下[HashMap]的问题: 1.多线程put操作后,get操作导致死循环.2.多线程put非NULL元素后,get操作得到NULL值.3.多线程put操作,导致元素丢失. 本次主要关注[Has ...
- ASP.NET多线程下使用HttpContext.Current为null解决方案 2015-01-22 15:23 349人阅读 评论(0) 收藏
问题一:多线程下获取文件绝对路径 当我们使用HttpContext.Current.Server.MapPath(strPath)获取绝对路径时HttpContext.Current为null,解决办 ...
随机推荐
- ICLR 2024 | Mol-Instructions: 面向大模型的大规模生物分子指令数据集
Mol-Instructions: 面向大模型的大规模生物分子指令数据集 发表会议:ICLR 2024 论文标题:Mol-Instructions: A Large-Scale Biomolecula ...
- 小知识:MySQL配置文件优先级
今天在RHEL7上,严格按之前的安装规范文档,部署MySQL环境时,发现通过服务的方式启动MySQL失败: 关键错误是: log-error set to '/var/log/mariadb/mari ...
- 华为云GaussDB支撑农行超级网银业务,性能和稳定性备受认可
数据库作为数据驱动业务创新和智慧银行建设的关键基础设施,在银行数字化变革中具有举足轻重的作用. 在金融科技发展和国家政策引领下,银行纷纷加快推进数字化转型时代,正在经历一场以科技引领.数据赋能.数字经 ...
- android mvvm实例解析
MVVM架构,将整个应用分为三层,View层,VM层,Model层.其中View层单向引用VM层,VM层单向引用Model层.如上图. 单向引用,而非双向引用,这是MVVM与MVP最大的区别.View ...
- Oracle system identifier already exists specify another SID
问题说明 Centos7重装Oracle,使用DBCA重新创建实例test的时候报错,中文意思是: Oracle系统标识符(SID)"test"已存在,请指定另一个SID. 问题原 ...
- 24个javascript最佳实践
1. 使用 === 代替 == JavaScript utilizes two different kinds of equality operators: === | !== and == | != ...
- Spring boot 2.0启动自动执行sql语句
项目地址:https://gitee.com/indexman/spring_boot_in_action 1.准备sql文件 将department.sql放到resources路径下 /* Nav ...
- Java并发编程实例--7.守护(Damon)线程
Java有一种特殊线程叫守护(后台)线程. 1.这类线程拥有非常低的优先级且通常只是在没有其他线程运行的情况下执行. 2.其通常作为无线循环服务去执行某项任务. 3.不能让他们去执行重要任务因为你不知 ...
- C++ 多线程的错误和如何避免(1)
在终止程序之前没有使用 join() 等待后台线程 前提分析:线程分为 joinable 状态和 detached 状态 添加 .join() 这句代码的时候,就表示主线程需要等待子线程运行结束回收 ...
- Go微服务框架go-kratos实战学习06:配置中心使用-nacos作为配置中心和 file作为配置存储
一.kratos 配置介绍 配置文件的作用就是把一些会变化的配置项单独存放,与程序相剥离. 把配置项进行单独管理. kratos 支持多种形式的配置, 比如 file,环境变量. 还支持一些配置软件, ...