当前位置:
首页 > Python基础教程 >
-
并发系列64章(并行编程)第五章
前言
并行编程,先来看下概念。并行编程用于分解计算密集型的任务片段,并将它们分配给多个线程。
划重点,这个是计算密集型的东西,而不是IO密集型。也就是说切割成的片段用于计算使用cpu计算,而不是内存。
如果一个操作时内存密集型那么并行处理是会起反的效果的,因为io意味着等待。原本等待一段的,现在每一段都要等待。
数据的并行处理
class Program
{
static void Main(string[] args)
{
List<int> intlist = new List<int>();
intlist.Add(1);
intlist.Add(2);
intlist.Add(3);
intlist.Add(4);
RotateMatrices(intlist);
Console.ReadKey();
}
private static void RotateMatrices(List<int> intlist)
{
Parallel.ForEach(intlist, arg =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
});
}
}
结果是:
上述得出一个结论,不是说并行的每一个都是在不同线程中,而是说并行的任务可能在同一线程。
注意:因为可能在不同线程中,对于公共变量注意锁。
并行聚合
上述并行中,现在有一个需求就是,让他们并行加上某个数,并得出他们的结果。
class Program
{
static void Main(string[] args)
{
List<int> intlist = new List<int>();
intlist.Add(1);
intlist.Add(2);
intlist.Add(3);
intlist.Add(4);
var reuslt=RotateMatrices(intlist);
Console.WriteLine(reuslt);
Console.ReadKey();
}
private static int RotateMatrices(List<int> intlist)
{
object mutex = new object();
int result = 0;
Parallel.ForEach(source: intlist, localInit: () => 1, body: (item, state, localvalue) =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
return item + localvalue;
},
localFinally: localresult =>
{
lock (mutex)
{
result += localresult;
}
}
);
return result;
}
}
localInit: () => 1 设置了为1,然后并行执行了body部分,最后得出结果相加。
从上面可以得出,并行编程其实是阻塞的。如果要达到更好的效果,需要结合异步编程。
上面还有个state 没有用上:
(item, state, localvalue)
这个state 可以 state.stop(); 停止
state.break() 跳出循环。
上面这样计算是有问题的:
class Program
{
static void Main(string[] args)
{
List<int> intlist = new List<int>();
for (int i = 0; i < 1000; i++)
{
intlist.Add(1);
intlist.Add(2);
intlist.Add(3);
intlist.Add(4);
}
var reuslt=RotateMatrices(intlist);
Console.WriteLine("查看result:"+reuslt);
Console.ReadKey();
}
private static int RotateMatrices(List<int> intlist)
{
object mutex = new object();
int result = 0;
Parallel.ForEach(source: intlist, localInit: () => 1, body: (item, state, localvalue) =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
return item + localvalue;
},
localFinally: localvalue =>
{
lock (mutex)
{
result += localvalue;
}
}
);
return result;
}
}
第一次的结果:
第二次的结果:
两次结果不一致。
惊喜不惊喜开心不开心?
刚开始我也很迷茫,后来看了一下群里的大佬点播了一下。
请跑一下下面的,一切都会很清晰的。
private static int RotateMatrices(List<int> intlist)
{
object mutex = new object();
int fornumber = 0;
int tasknumber = 0;
int result = 0;
Parallel.ForEach(source: intlist, localInit: () => 1, body: (item, state, localvalue) =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
Console.WriteLine("查看localvalue:"+ localvalue);
Console.WriteLine("item:"+item);
Interlocked.Add(ref fornumber, 1);
return item+localvalue;
},
localFinally: localvalue =>
{
Console.WriteLine("查看Tasklocalvalue:" + localvalue);
lock (mutex)
{
result += localvalue-1;
}
Interlocked.Add(ref tasknumber, 1);
}
);
Console.WriteLine("fornumber:"+fornumber);
Console.WriteLine("tasknumber:" + tasknumber);
return result;
}
重点部分我画了红字:
简化版:
intlist.AsParallel().Sum();
intlist.AsParallel().Aggregate(seed: 0, func: (sum, item) => sum + item);
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式