惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
A
About on SuperTechFans
G
Google Developers Blog
B
Blog RSS Feed
F
Fortinet All Blogs
WordPress大学
WordPress大学
Recent Announcements
Recent Announcements
Hugging Face - Blog
Hugging Face - Blog
Y
Y Combinator Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
Jina AI
Jina AI
IT之家
IT之家
P
Proofpoint News Feed
美团技术团队
量子位
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
B
Blog
有赞技术团队
有赞技术团队
U
Unit 42

博客园 - yahle

Performance Improvements in .NET 9 [翻译 by chatglm] Performance Improvements in .NET 8 & 7 & 6 -- File I/O【翻译】 Performance Improvements in .NET 8 & 7 & 6 -- String【翻译】 Performance Improvements in .NET 8 & 7 & 6 -- Thread【翻译】 Performance Improvements in .NET 8 -- Exceptions & Reflection & Primitives【翻译】 Performance Improvements in .NET 8 -- Native AOT & VM & GC & Mono【翻译】 Performance Improvements in .NET 8 -- JIT部分翻译 mysql迁移到pqsql笔记 一个.net6开发的截图后ocr小工具 云服务器内容迁移 总结 立个铁矿石的flag,从7月初开始,铁矿石的库存,可能要进入累库存阶段了. 让你的 vs code 跑在云上,用手机浏览器就能写代码 - yahle ASP.NET Core 2 High Performance 目录和读书笔记 - yahle [转帖]无网络离线安装 vs2017 - yahle - 博客园 centos下 .net core 2.0 升级 到 2.1 遇到的一个小问题 .net core jwt 入门记录 GTX 750TI 使用 ffmpeg 时无法用 GPU HEVC(h.265) 进行加速 [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象 [翻译] 编写高性能 .NET 代码--第二章 GC -- 将长生命周期对象和大对象池化
.net core 多线程下使用 Random 会出现bug
yahle · 2022-09-08 · via 博客园 - yahle

.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() 最优。两者差距有一倍。
但是,指定随机种子后,两者就没有差距了,这就有点让人想不通了。