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

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
The GitHub Blog
The GitHub Blog
C
Check Point Blog
博客园_首页
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
F
Full Disclosure
Microsoft Security Blog
Microsoft Security Blog
爱范儿
爱范儿
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
K
Kaspersky official blog
博客园 - 司徒正美
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Cisco Talos Blog
Cisco Talos Blog
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
V
V2EX - 技术
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Spread Privacy
Spread Privacy
罗磊的独立博客
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
SecWiki News
SecWiki News
Schneier on Security
Schneier on Security
O
OpenAI News
Jina AI
Jina AI
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog RSS Feed
I
InfoQ
D
Docker
P
Palo Alto Networks Blog
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
博客园 - Franky
B
Blog
Scott Helme
Scott Helme
博客园 - 叶小钗
D
DataBreaches.Net

博客园 - 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 入门记录 - yahle GTX 750TI 使用 ffmpeg 时无法用 GPU HEVC(h.265) 进行加速 [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象 - yahle [翻译] 编写高性能 .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() 最优。两者差距有一倍。
但是,指定随机种子后,两者就没有差距了,这就有点让人想不通了。