TPL Part3 -- 数据共享
来源:互联网 发布:网络在线咨询图片 编辑:程序博客网 时间:2024/06/08 12:36
问题:多个Task需要操作共享变量时,会有资源竞争的问题,例如下段代码示例:
void Main(){ int shared = 0; Task[] tasks = new Task[10];for (int i = 0;i < 10; i++) {//create a new tasktasks[i] = new Task(() => {// entera loop for 1000 balance updatesfor(int j = 0;j < 1000; j++) {//update the balanceshared++;}});// startthe new tasktasks[i].Start();} Task.WaitAll(tasks); Console.WriteLine(string.Format("shared : {0}",shared));Console.ReadLine();}
期望结果:10000,可实际结果每次都不一样(第一次为8093)。
解决方案1:隔离
即每个Task独享一个变量,最后合并结果:
void Main(){ Task<int>[] tasks = new Task<int>[10];for(int i = 0;i < 10; i++) {//create a new taskvar taskVal = 0;tasks[i] = new Task<int>((v)=> {int val = int.Parse(v.ToString());// enter a loop for 1000 balance updatesfor(int j = 0;j < 1000; j++) {//update the balanceval++;}return val;},taskVal);// start the new tasktasks[i].Start();} int result = 0;for(int i = 0;i < 10; i++) {result+= tasks[i].Result;}Console.WriteLine(string.Format("result : {0}",result));Console.ReadLine();}
每个线程独享1个变量,进行计算返回结果,最后合并结果(在tasks[i].Result时,Task会阻塞)。
方案2:加锁
相信读者对锁已经不再陌生,它在解决资源竞争问题时是经常出现的,思路就是设定关键区域,把那部分操作变成同步的(同时只允许一个线程操作)。
锁的种类
lock :重量级锁,会带来线程切换的开销。
lock (lockObj) {...critical region code...}
等价于:
bool lockAcquired;try {Monitor.Enter(lockObj, reflockAcquired);...critical region code...} finally {if (lockAcquired)Monitor.Exit(lockObj);}
System.Threading.Interlocked:轻量级锁,会调用底层硬件特性进行优化,对于只需要操作整数++或整数--的情况很适用。常见方法:
● Add:整数加和
● Exchange:赋值
● Increment:递增
● Decrement :递减
CompareExchange<T>:比较两个数,相等则赋值
System.Threading.Mutex:可用于完成跨进程资源同步(使用命名的mutex)。
使用Synchronize特性:声明式加锁,会对类中的所有成员,方法实现锁机制,谨慎使用。
SpinLock:轻量级锁。通常对于短时间内(例如在指令级别)资源同步的情况,性能会高于monitor或SlimReaderWriterLock。
SlimReaderWriterLock:轻量级锁。优势在于读写锁分离。避免在读锁中打开写锁,会造成死锁。即便可以通过EnterUpgradeableReadLock来实现这种场景,仍然不推荐这样做。
几种并发集合
在多线程场景中,没有并发集合之前,使用集合时需要手动加锁来解决资源共享的问题,以下四种并发集合可以使我们从这种问题中release出来,在多线程场景中可以直接拿来用:
ConcurrentQueue,ConcurrentStack,ConcurrentBag,ConcurrentDictionary。
- TPL Part3 -- 数据共享
- 《C++ Concurrency In Action》part3 线程间共享数据
- TPL
- tpl渲染表格以后刷新表格数据
- part3
- PART3
- Remind-You Part3. Python-Sqlite记录数据
- 网络爬虫,python和数据分析学习--part3
- TPL脚本语言
- TPL dataflow
- .tpl模板
- tpl 文件
- 数据共享
- Smarty模版引擎 获取各种数据分配给tpl模版文件
- 关于使用tpl模板如何从模板中取数据放入js中
- 数据持久,数据共享
- TPL + Json + PHP = TPL + JSPT
- struts part3
- 多线程——安全问题
- PowerDesigner 反向 PostgreSQL 时 Unable to list the columns. SQLSTATE =22003 的解决方法
- java文件读写操作大全
- puppet 安装及应用
- 4.25
- TPL Part3 -- 数据共享
- 第七周 课后实践:项目一——图形用户界面(GUI)应用程序开发初体验
- 阿里巴巴前端面试题:三列布局知多少?
- Visual Studio 2013 编写汇编代码
- COM和DLL的一些区别
- LAMP环境的搭建及注意点
- 面试常见问题知识点汇总(干货)
- Volley框架剖析( 二)从开始到结束
- linux系统中如何查看日志 (常用命令)