我在应用多线程加速图像处理(具体参见图像处理的多线程计算)的过程中,曾遇到过一个线程同步的问题。多线程对图像不同子块进行处理,再合成。结果发现最终不是全部子块都处理成功,有的子块好像没有被处理。而且发现结果图像中哪个子块没有被处理好像是随机发生的,没有处理的子块个数也不固定。检查程序,确信所有的子块都处理了,所以怀疑各个子线程计算子块后,在更新图像时线程同步出了问题。

有一个子图没有处理

在对结果图像进行更新是用到了DC的BitBlt(),多线程计算时对图像数据是进行了保护的。在更新结果图像时,原来是这么写的。

CDC* pSrcDC = Src.GetDC();
CSingleLock sLock(&Src.m_Critical, TRUE);
BOOL ret = m_memDC.BitBlt(SrcX, SrcY, nWidth, nHeight, pSrcDC, SrcX, SrcY, SRCCOPY);
sLock.Unlock();
Src.ReleaseDC(pSrcDC);

m_memDC是设备兼容的内存DC,最后要写到显示设备。Src是计算后的完整图像位图实例,Src.GetDC()和Src.ReleaseDC(pSrcDC)包含了把Src选入和选出pSrcDC的操作。各计算子线程会异步对Src的各个子块进行更新。每次BitBlt()也是对要更新的子块进行操作,写到m_memDC,对BitBlt()也已经添加了保护,按理说不应该有问题的。但是其他地方都检查过了,只有这里值得怀疑。只有更新没有成功,才可能出现这种情况了。试着对整个DC操作加上保护,改成这样:

CSingleLock sLock(&Src.m_Critical, TRUE);
CDC* pSrcDC = Src.GetDC();
BOOL ret = m_memDC.BitBlt(SrcX, SrcY, nWidth, nHeight, pSrcDC, SrcX, SrcY, SRCCOPY);
Src.ReleaseDC(pSrcDC);
sLock.Unlock();

这样一改,结果马上就正确了。按原来的想法,Src是作为只读的源来对m_memDC更新的,而且每次只更新一个子块。如果同时有其他的子线程在对Src进行其他子块的更新,也不是这里BitBlt()所用到的目标子块。按理来说,即使这里不加保护,应该也不会对最后的结果有影响的。而我原来的代码也对BitBlt()加了保护,只是没有把位图选入选出DC的操作保护起来。然而,实际结果却不是这样。也就是说,在一个位图被选入DC了以后,即使这个位图是作为源,还没有被读取的时候,如果其他线程对这个位图进行了修改,写操作,这个修改可能丢失。下次再对m_memDC更新这个修改,由于Src中的这个修改已经丢失,自然结果就不对了。所以对这个位图保护要从被选入DC之前就开始。

难道在把图像选入DC(调用SelectObject())时,是把图像拷贝到DC的?因此如果不对位图在被选入之前进行保护,把图像选出DC时,内容从DC拷贝回到图像,有可能把图像中别的线程更新的部分覆盖了。所以只有在把图像选入DC之前就保护起来,才能保证每个线程选入DC的图像都是最新的,同时保证在对m_memDC更新时,别的线程不能更新Src。不过这样吧内存向DC拷来拷去,似乎从效率上来说不太好吧。具体到底如何,还真不清楚了。如果有了解的朋友,还望告知。

多线程图像处理中对选入DC的位图保护的更多相关文章

  1. 图像处理中任意核卷积(matlab中conv2函数)的快速实现。

    卷积其实是图像处理中最基本的操作,我们常见的一些算法比如:均值模糊.高斯模糊.锐化.Sobel.拉普拉斯.prewitt边缘检测等等一些和领域相关的算法,都可以通过卷积算法实现.只不过由于这些算法的卷 ...

  2. hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。

    /** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...

  3. paper 119:[转]图像处理中不适定问题-图像建模与反问题处理

    图像处理中不适定问题 作者:肖亮博士 发布时间:09-10-25 图像处理中不适定问题(ill posed problem)或称为反问题(inverse Problem)的研究从20世纪末成为国际上的 ...

  4. zz剖析为什么在多核多线程程序中要慎用volatile关键字?

    [摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...

  5. [原创]纯JS实现网页中多选复选框checkbox和单选radio的美化效果

    图片素材: 最终效果图: <html><title> 纯JS实现网页中多选复选框checkbox和单选radio的美化效果</title><head>& ...

  6. 在多线程环境中使用CoreData

    在多线程环境中使用CoreData BY 子非鱼 · 2014 年 10 月 13 日   上回书说道,其实CoreData学起来也没有很复杂,我们其实增删改查都和别的ORM大同小异.但是世界总是很复 ...

  7. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

  8. JS 获取select(多选下拉)中所选值的示例代码

    通过js获取select(多选下拉)中所选值,具体实现如下,有需要的朋友可以参考下,希望对大家有所帮助 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML ...

  9. 关于python多线程编程中join()和setDaemon()的一点儿探究

    关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的  ...

随机推荐

  1. ubuntu12.04下安装pptp_vpn服务器

    1.下载安装apt-get install pptpd 2.配置/etc/pptpd.confvim /etc/pptpd.conf添加下面两行(在配置文件的最后取消注释修改IP即可)localip ...

  2. jQuery_第一章_JavaScript基础

    JavaScript基础 JavaScript不难,但是对于初学者来讲比较的怪异. 是一种客户端语言,在浏览器执行的.是一种脚本语言,直接就能解释执行的叫脚本代码.像dos命令还有SQL也是. 为什么 ...

  3. iOS开发之Runtime常用示例总结

    经常有小伙伴私下在Q上问一些关于Runtime的东西,问我有没有Runtime的相关博客,之前还真没正儿八经的总结过.之前只是在解析第三方框架源码时,聊过一些用法,也就是这些第三方框架中用到的Runt ...

  4. 第一章 Java语言概述2

    一.编写第一个Java应用程序 1.下载.安装JDK 官方网址:www.oracle.com java.sun.com 安装JDK 傻瓜式安装,下一步即可. 建议:安装路径不要有中文或者特殊符号,如空 ...

  5. EFcore与动态模型

    在开发商城系统的时候,大家会遇到这样的需求,商城系统里支持多种商品类型,比如衣服,手机,首饰等,每一种产品类型都有自己独有的参数信息,比如衣服有颜色,首饰有材质等,大家可以上淘宝看一下就明白了.现在的 ...

  6. 在.NET Core控制台应用程序中使用强类型配置

    想象一下,你写一个控制台应用程序,你想要从配置文件中以强类型方式读取配置. .NET Core 可以帮助我们解决. 通常我会在ASP.NET Core MVC中演示,但简单起见,只在控制台应用程序中演 ...

  7. 为 instance 配置静态 IP - 每天5分钟玩转 OpenStack(157)

    这是 OpenStack 实施经验分享系列的第 7 篇. 传统运维中为服务器配置静态 IP 是再常见不过的了.但在 OpenStack 环境下只能指定 network,IP 都是 Neutron 从 ...

  8. php封装+租房子练习题

    第一个页面DBDA.class.php <?php class DBDA { public $host = "localhost"; public $uid = " ...

  9. Asp.Net 常用工具类之加密——对称加密DES算法(2)

    又到周末,下午博客园看了两篇文章,关于老跳和老赵的程序员生涯,不禁感叹漫漫程序路,何去何从兮! 转眼毕业的第三个年头,去过苏州,跑过上海,从一开始的凌云壮志,去年背起行囊默默回到了长沙准备买房,也想有 ...

  10. 构建Docker平台【第三篇】安装 kubernetes 组件

    第一步:准备 1. 安装包: kubeadm-1.6.0-0.alpha.0.2074.a092d8e0f95f52.x86_64.rpm kubernetes-cni-0.3.0.1-0.07a8a ...