手机号码网站建设长沙企业网站设计

当前位置: 首页 > news >正文

手机号码网站建设,长沙企业网站设计,机电网站模板,开源做网站需要申请账号吗文章目录 为什么需要创建并发限制#xff1f;不用并发限制会怎样#xff1f;怎么设置并发限制如果任务是I/O密集型#xff0c;可以适当放宽并发数吗#xff1f;线程是有限资源#xff0c;那4核8线程的CPU#xff0c;线程数就是8吗#xff1f; CPU的“线程”与操作系统的… 文章目录 为什么需要创建并发限制不用并发限制会怎样怎么设置并发限制如果任务是I/O密集型可以适当放宽并发数吗线程是有限资源那4核8线程的CPU线程数就是8吗 CPU的“线程”与操作系统的“线程”总结 protected async Task OperateModbusObjectToEnabledClientsAsync(FuncModbusObjectDemo, Task func, string operationName ){try{if (func null)throw new ArgumentNullException(nameof(func));// 获取所有已启用写操作的客户端var enabledClients _clientProvider.GetEnabledClients();if (!enabledClients.Any()){StatusMessage No enabled clients found!;logger.Debug(StatusMessage);return;}logger.Trace(Action客户端数量:{0},写操作开始:{1}, enabledClients.Count(), operationName);// 使用一种轻量级的信号量来创建并发限制用于限制同时运行的任务数量避免同时处理太多客户端。using var semaphore new SemaphoreSlim(Environment.ProcessorCount);var tasks new ListTaskClientOperationResult();foreach (var client in enabledClients){tasks.Add(ProcessClientAsync(client, func, semaphore));}// 等待所有任务完成设置超时时间var timeoutTask Task.Delay(TimeSpan.FromSeconds(20)); // 设置20秒超时// 等待所有任务和超时任务完成。// 使用Action版本(无返回值)这里的WhenAll只会等待Task.Run完成而不会等待action中的异步操作。// 使用FuncTask的版本这里的WhenAll会等待所有异步操作完成。var completedTask await Task.WhenAny(Task.WhenAll(tasks), timeoutTask);if (completedTask timeoutTask)//如果是超时任务完成则报错{logger.Error(\(Operation {operationName} timed out after 20 seconds);StatusMessage \)Operation {operationName} timed out;return;}var results await Task.WhenAll(tasks);logger.Trace(Action客户端数量:{0},写操作结束:{1}, enabledClients.Count(), operationName);ProcessResults(results, operationName);}catch (Exception ex){StatusMessage \(Error in {operationName}: {ex.Message};logger.Debug(StatusMessage);}}private async TaskClientOperationResult ProcessClientAsync(IModbusTcpClient client, FuncModbusObjectDemo, Task func, SemaphoreSlim semaphore){try{// 等待获取信号量await semaphore.WaitAsync();logger.Trace(信号量数量{0}, semaphore.CurrentCount);if (!client.IsConnected){return new ClientOperationResult{Client client,Success false,Error Not connected};}// 直接等待异步操作不需要 Task.Runawait client.TryGetModbusObjectDemoAsync(func);return new ClientOperationResult{Client client,Success true,Error string.Empty};}catch (Exception ex){logger.Error(\)Error processing client {client.Name}: {ex.Message});return new ClientOperationResult{Client client,Success false,Error ex.Message};}finally{semaphore.Release();}}为什么需要创建并发限制 原因一线程资源是有限的 线程不是“无限”资源。每创建一个线程都会占用一定的内存和CPU调度资源。如果有很多客户端比如几十、几百个每个都开一个线程去处理系统很快就会因为线程数过多而变慢甚至崩溃线程上下文切换开销大内存消耗大。 原因二防止“线程风暴” 如果不加限制所有任务会同时并发执行可能导致CPU、内存、网络等资源被瞬间耗尽影响整个系统的稳定性。 原因三提升整体吞吐量和响应性 合理的并发数可以让CPU和I/O资源得到充分利用同时又不会让系统过载。这样可以保证每个任务都能在合理的时间内完成系统整体更平稳。
不用并发限制会怎样 可能会出现线程爆炸导致系统变慢甚至崩溃。任务之间会频繁切换CPU大部分时间都在做“线程切换”而不是“真正的工作”。系统响应变慢甚至出现死锁、内存溢出等问题。 怎么设置并发限制 如示例代码中使用轻量级的信号量SemaphoreSlim用于限制同时运行的任务数量。可以把它理解为“并发闸门”只有拿到“通行证”的任务才能执行其他任务要等前面的任务释放“通行证”后才能继续。 Environment.ProcessorCount 的含义 Environment.ProcessorCount 返回当前机器的逻辑处理器CPU核心数量。例如4核8线程的CPU这个值就是8。也就是说通过信号量SemaphoreSlim限制同时只允许8个线程同时处理。 为什么用它 这是一个经验值通常来说CPU密集型任务的并发数设置为核心数可以获得最优性能。即使是I/O密集型任务设置为核心数也能保证不会有太多任务同时抢占CPU避免线程切换开销过大。这样做的好处是既能利用多核CPU的并发能力又不会让系统资源被过度消耗。举例说明 假设你有100个客户端如果不加限制100个任务会同时执行系统压力很大。如果用 SemaphoreSlim(8)每次只允许8个任务并发执行其他的排队等前面的执行完再继续。 如果任务是I/O密集型可以适当放宽并发数吗 可以对于I/O密集型任务比如网络、磁盘操作可以适当把并发数调大一些比如2~4倍核心数但也要根据实际测试和服务器能力来调整。但绝不能无限制地放大否则还是会有资源耗尽的风险。 线程是有限资源那4核8线程的CPU线程数就是8吗 我们可以创建远远多于8个线程比如100、1000甚至更多但这样做会带来 内存消耗每个线程有自己的栈空间通常1~2MB线程切换的CPU开销上下文切换系统调度压力 实际“有限资源”取决于 你的机器内存有多少你的操作系统允许的最大线程数你的应用场景CPU密集型还是I/O密集型 一般来说 线程数在几十到几百是没问题的取决于内存和场景但同一时刻能被CPU真正执行的线程数就是逻辑核心数比如8 这就要引入下一个话题CPU的“线程”与操作系统的“线程” CPU的“线程”与操作系统的“线程” CPU的线程比如4核8线程指的是CPU能同时并行执行的最大任务数也就是“并发执行单元”。 4核8线程代表有4个物理核心每个核心支持超线程Hyper-Threading所以一共8个“逻辑核心”。 这意味着最多有8个任务可以真正同时被CPU执行。 操作系统的线程比如C#里的Thread/Task是软件层面的调度单元。 操作系统可以创建成百上千个线程但同一时刻只有最多8个线程能被CPU真正执行在4核8线程的机器上。 其他线程会被挂起、等待操作系统会不断切换它们上CPU。
总结 4核8线程的CPU不是说你只能创建8个线程而是同一时刻最多8个线程能被CPU并行执行。你可以创建更多线程但会带来资源消耗和调度开销。线程是有限资源但这个“有限”不是8而是受内存、操作系统和应用场景共同决定的。用 Environment.ProcessorCount 作为并发限制是为了让你的程序既高效又不会让系统过载频繁在线程上下文中切换。