当多线程协作处理同一个数据源时,可以使用分区器,有两种分区器:
1.范围分区器
范围分区器又称静态分区器,即每个线程处理的数据项个数是相同的,根据数据源集合的索引来划分给每个线程一个数据范围。比如4个线程处理有100个元素的数组,级分区器会依次给每个线程分配数组索引为0~24,25~49,50~74,75~99四个范围的元素,每个范围25个数组元素,如果处理每个元素的耗时不同,级分区器不会动态调配每个线程处理的工作量。当一个线程处理完25个数组元素后,其它线程仍还没有处理完,空闲的线程不会帮繁忙线程处理数据。
但由于每个线程处理的数据项个数在一开始就已经分配完成,不会涉及锁的问题,这排除了锁带来的性能问题。
这种分区器适合,数据项元素较多(数据元素越多,当使用动态分区器处理的时候,锁冲突的次数就会越多,锁带来的性能影响就会越明显),每个元素的处理时间差不多的情形。
2.块分区器
块分区器又称动态分区器,当多个线程处理同一个数据源时,它们会分别从数据源请求部分数据,当请求的数据处理完成之后,从数据源请求部分数据。比如,4个线程(称为A,B,C,D)处理100个元素的数组,它们会各自请求10个元素进行处理,假设A线程优先处理完这10个元素,随后其会再去请求10个元素,以此类推,最后是:A线程处理70个元素,B线程处理10个元素,C线程处理10个元素,D线程处理10个元素。这就有点“能者多劳”的意思,先处理完一个小块数据元素的线程会再去请求数据元素来执行,帮助处理的慢的线程来处理数据。
由于同一个数据源会被不同的线程不断的请求数据块,所以,资源争用导致的锁的问题是不可避免的,并且,如果每个块中的元素越小,则锁冲突的次数将会越多。
块分区器适合每个元素的处理时间相差很大,且数据项元素较少的情形。
C#中的分区器详见文档:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-implement-dynamic-partitions
https://stackoverflow.com/questions/17785049/parallel-for-partitioning
线程间的负载均衡
最新推荐文章于 2025-03-31 16:15:43 发布