qt容器在并发时需要注意的地方

最近用tbb和qt写了一个延时摄影后期控制镜头的工具,主要就是扫描目录下所有图片,按照给定参数截取图片中某区域并另存,模拟镜头摆动。

扫描后的图片路径保存在qlist内,作为只读数据,交由tbb的parellel_for处理。tbb并行对qlist每个元素内的路径对应的图片进行读取,裁剪,另存操作(磁盘是ssd,这个程序在8线程的机器上,可令cpu满负荷)。理想是美好的,现实是残酷的。

前提,qlist(不光qlist了,qt很多数据结构都)实现了copy on write,qlist的索引操作符分为const和非const(const[] 和 [])

首先,界面拥有路径qlist,并按值传递给tbb处理类。

接着,执行过程中遇到了tbb处理线程崩溃的现象,发现从qlist索引出来的路径是无效的QString,调试分析发现,当线程A对qlist索引时,触发了qlist的copy on wirte机制(虽然是按值传递,但仍然与界面的qlist引用同一份数据),机制在没有执行完成的时后,线程B又对qlist进行索引,所以线程B得到的qlist元素是无效的。避免这种情况发生,就要使用const[] 。

个人感想,copy on write机制对于数据平行运算(data parallel)来说属于坑爹的机制,data parallel一个相当重要的前提是,对容器(同一个或不同的)元素的并发读写不会改变容器自身的状态(虽然对于单个元素来说可能存在竞争,但对于容器来说不存在竞争),最简单就例如C语言,对数组元素的读写不会改变数组状态,又例如std::vector,再高级点就例如GPU对render target,memory object,random access view这类对象的并发操作不会改变对象的状态。而qlist只能提供元素只读,同时对元素读写就可能悲剧了。还好,这个工具只会对qlist元素并发读,不需要读写。注意是qlist内的元素,不是qlist容器并发读

题外话,处理完这个问题后,又出现另一个问题,调试模式下输出文件数少了,最后发现是malloc返回空指针,erron是12,无法分配内存,悲剧啊,图片文件过大了,线程过多了。我处理的图片分辨率是7000*4000,tbb线程有两个图片对象,一个输入一个输出,机器是8线程的cpu,程序是32位,算了一下,2G内存真有可能不够,特别是调试模式,看来要迁移到64位才行。

qt容器在并发时需要注意的地方

时间: 2024-10-26 08:56:29

qt容器在并发时需要注意的地方的相关文章

并发编程(9):同步类容器与并发类容器

1.同步类容器 同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作. 复合操作,如: 迭代(反复访问元素,遍历完容器中所有的元素) 跳转(根据指定的顺序找到当前元素的下一个元素) 条件运算 这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,最经典的就是ConcurrentModificationException,原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题. 同步类容器:如古老的Vector.HashTble.这

线程学习--(七)单例和多线程、同步类容器和并发类容器

一.同步类容器 同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作.复合类操作如:迭代(反复访问元素,遍历完容器中的所有元素).跳转(根据指定的顺序找到当前元素的下一个元素).以及条件运算.这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,最经典的便是ConcurrentModificationException,原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题. 同步类容器:如古老的Vector/HashTable.

QT开发(六)——QT容器组件

QT开发(六)--QT容器组件 QT中有九种容器组件,分别是组合框QGroupBox.滚动区QScrollArea.工具箱QToolBox.选项卡QTabWidget.控件栈QWidgetStack.框架QFrame.组件QWidget.MDI窗口显示区QMdiArea.停靠窗口QDockWidget. 一.QGroupBox分组框 1.QGroupBox组件简介 QGroupBox为构建分组框提供了支持.分组框通常带有一个边框和一个标题栏,作为容器部件来使用,在其中可以布置各种窗口部件.分组框

'QObject& QObject::operator=(const QObject&)' is private——无法将自定义的QObject子类放入Qt容器(container)中

先贴出问题的代码: 1 #include<QCoreApplication> 2 classMyObject:publicQObject 3 { 4 public: 5 MyObject(QObject*parent =0): 6 QObject(parent) 7 { 8 } 9 private: 10 int m_id; 11 }; 12 int main(int argc,char*argv[]) 13 { 14 QCoreApplication a(argc, argv); 15 QL

【JAVA并发】同步容器和并发容器

同步容器类 同步容器类的创建 在早期的JDK中,有两种现成的实现,Vector和Hashtable,可以直接new对象获取: 在JDK1.2中,引入了同步封装类,可以由Collections.synchronizedXxxx等方法创建: 同步容器类的问题 同步容器类虽然都是线程安全的,但是在某些情况下(复合操作),仍然需要加锁来保护: 常见复合操作如下: 迭代:反复访问元素,直到遍历完全部元素: 跳转:根据指定顺序寻找当前元素的下一个(下n个)元素: 条件运算:例如若没有则添加等: 举个条件运算

Java学习笔记—多线程(同步容器和并发容器)

简述同步容器与并发容器 在Java并发编程中,经常听到同步容器.并发容器之说,那什么是同步容器与并发容器呢?同步容器可以简单地理解为通过synchronized来实现同步的容器,比如Vector.Hashtable以及SynchronizedList等容器,如果有多个线程调用同步容器的方法,它们将会串行执行. 可以通过查看Vector.Hashtable等同步容器的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并在需要同步的方法上加上关键字synchronized,但在某

Java并发-从同步容器到并发容器

引言 容器是Java基础类库中使用频率最高的一部分,Java集合包中提供了大量的容器类来帮组我们简化开发,我前面的文章中对Java集合包中的关键容器进行过一个系列的分析,但这些集合类都是非线程安全的,即在多线程的环境下,都需要其他额外的手段来保证数据的正确性,最简单的就是通过synchronized关键字将所有使用到非线程安全的容器代码全部同步执行.这种方式虽然可以达到线程安全的目的,但存在几个明显的问题:首先编码上存在一定的复杂性,相关的代码段都需要添加锁.其次这种一刀切的做法在高并发情况下性

多并发时支付如何保持账户余额的一致性?

转载:http://costlend.com/2016/03/14/dispatch-pay-balance-keep-consistence/ 不管是电商,还是O2O业务都会涉及到支付,而且多速情况下流量比较大,尤其是在做活动的时候.一般支付系统主要有充值,扣费,提现,转账等功能,那么在有些业务场景下,尤其是多并发的情况下,我们在做扣费业务操作时该怎样去保持账户余额的一致呢? Java开发人员可能第一个想法就是在调用扣减的DAO的方法上加上一个synchronized关键字,这个解决办法在单节

LNMP高并发时502

之前php-fpm配置: 单个php-fpm实例,使用socket方式,内存8G 静态方式,启动php-fpm进程数300,具体参数如下 1 2 3 4 5 6 7 8 9 10 11 listen = /tmp/php-cgi.sock #listen = 127.0.0.1:9000 listen.backlog = 2048 listen.allowed_clients = 127.0.0.1 pm = static pm.max_children = 300 pm.start_serve