线程真不是好玩的

原创 2005年05月06日 15:58:00

早就耳闻线程是一个可怕的东西,弄不好会让人疯掉的,所以长期以来,我一向对线程相当谨慎,甚至有点敬而远之,我相信
1) 决不设计过于复杂的多线程代码;
2) 必须依靠多线程实现的逻辑,一定要能够相当简单。
如果多线程逻辑复杂了,到时候出了错都不知道什么地方错了,而且错误无法复现,这是最要命的。

最近需要用QtE做一个UI相关的库,问题是,使用这个UI库的程序是在非UI线程上调用这个库的,而QT的创作者Trolltech的技术人员谆谆教诲 我们不要在非UI线程上做UI操作。说道这个要求,倒不是只有QT这么干的。因为UI操作最终要作用于存储显示内容的内存资源,如果容许多个线程能够操作 这个资源,毫无疑问要想不出岔子,就需要用上线程同步,线程同步的代码谁来写呢?如果UI库自己来作同步,那么效率就很成问题,如果让使用UI库的 programmer来做同步,那么programmer又会很难受,所以几乎所有的UI库干脆要求只有一个线程能够做UI操作,这个线程就是UI线程, 其工作就是和一个抽水泵一样不停的接受事件然后分配给特定的widget。但是在QT上面,如果违反这个原则,在非UI线程上做UI操作,很有可能不会发 生任何异常,但在某个时候,问题又会产生,“偷走你的银行存款,偷走你的女朋友“(Trolltech开发人员如此描述可能发生的问题),所以,要想保证 质量,必须保证所有的UI操作都在UI线程上面进行。

回到我的工作上来, 为了达到能够在非UI线程(在QT的应用程序里,除了UI进程,其他的进程都叫“非UI线程“),我不得不用上postEvent,用这种方式,在非UI 线程上抛出一个event,这个event会进入进程的event loop,然后被UI线程的抽水泵抓住,这样,非UI线程就通过这种方式把UI操作转移到UI线程上。

一切都进行得很好,单元测试也很顺利,但是使用我的库的程序员报告说调用一个函数的时候偶尔会出现Segmentation Fault,因为不是总发生这种错误,第一反应就是和线程相关的逻辑有问题。为了复现这个错误,我编了一个只使用这个库里一个功能的程序,为了模拟在非 UI线程中调用这个函数,我在一个死循环中通过pthread_create创建线程,在线程里面创建并显示一个widget,然后隐藏并释放它。这也算 是一个压力测试。结果程序运行到261次循环的时候就被Killed了,这和报告的Segementation Fault不一样,Killed一般意味着内存不足了,我仔细看了一下库的代码,逻辑很简单,new过的东西都被delete了,应该不会产生内存泄露, 我有运行了一遍这个测试程序,还是被Killed了,而且还是杂261次循环的时候,我就心存疑问了,为什么总是在261次的时候,肯定是什么资源没有被 释放,261次之后就消耗光了。当天没有找出什么端倪来,在回家的路上想到,pthread_create一般是需要被pthread_join的,会不 会是因为没有pthread_join,所有有资源没有释放呢。第二天把程序修改了一下,不用pthread_join,可以把pthread的属性设成 不用join
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  pthread_t tid;
  pthread_create(&tid, &attr, &thread_show, this);
  pthread_attr_destroy(&attr);

这样killed的问题没有,但是,Segementation Fault的问题出现了,经过反复运行测试程序,发现Fault出现的地方总是在delete一个widget之后,原来,我原来的代码中虽然创建和显示 widget的code保证是在UI线程上执行的,但是delete这个widget却很马虎的是从非UI线程上执行的。把这个修改过来之后, Segementation Fault就再没发生过。

这个bug给了这样的教训
1) pthread_create产生的线程占用资源,通过pthread_join回收资源,或者设成detached thread,这样就不需要pthread_join了,线程结束运行自动释放资源;
2) 对UI的擦操作必须在UI线程上,不仅指的是widget的创建和显示,还包括widget的删除。

【全球囧闻】英国公投真不是逗你玩!“脱欧”龙卷风突袭全球……

夏至刚过不久,又到灾害性天气频发的时节了。昨天就有一场史无前例的龙卷风袭击了江苏盐城一带,连囧闻君的领导都被迫临时请假回苏北老家给丈母娘救灾,工作上的事只好就让那位熬夜看球看得要找老中医调理身体的女助...

Segmetation fault你来的真不是时候

问题是这样的,今天一个简单的C程序,用gcc编译成汇编语言后,本来想在里面改点东西,结果运行时就报了“Segmetation fault”。它丫来的还真不是时候,刚好最近正好烦它呢,谁知自己倒送上门来...

File Expert,这货真不是老外做的

File Expert,中文名:文件大师,可能有不少读者都在用或者用过。清一色的英文介绍,如果你不知道其开发者是什么人的话,你肯定不会发表评论;如果你知道他们的开发者是国人,你可能会冒出一句:装B...

任正非:不惑之年创立华为是生活所迫,CEO真不是人干的活

任正非:不惑之年创立华为是生活所迫,CEO真不是人干的活  人参与 | 时间:2016年11月20日 20:16  我创建了华为公司,当时在中国叫个体户,这么一个弱小的个体户...

linux ulimit的若干坑 - ulimit真不是乱设的

soft和hard一起设置才好使* soft nofile 1000000 * hard nofile 1000000如果只是设置一个,那么是不起作用的啥时候ulimit的设置才生效退出当前sessi...

android droiddraw 这么简单的功能都实现不了么?JAVA真不是人写的

在这里下的 http://code.google.com/p/droiddraw/ 需要root 的Linear layout打横,在属性,点了apply也不行,应该如何操作呢? 真想...
  • avi9111
  • avi9111
  • 2012年06月01日 17:57
  • 1911

「价值」我真不是买不起,而是要把钱花在了更有意义的地方

四年前的我还是一个傻了吧唧单身女孩,生活并未撕开面具对我露出凶残的真面目,于是我在追求自由、虚荣和玩乐的道路上一路狂奔,月月向银行举债。那时在电视台的工作保底收入有五千多,在外接点私活随随便便也有四五...

Google+就是Google+社交,但真不是社交网络

在科技界,Google+的表现,无论好坏都已成为一个热点新闻,很多人都认为这是一个社交网络,并将之与Facebook进行对比,有人说Facebook受到严重威胁,有人说Google+作为一个社交网络太...

“你成功不就是运气好吗”- 还真不是!

据说史蒂夫·乔布斯年轻时每天凌晨四点起床,九点前把一天工作做完。乔帮主说:自由从何而来?从自信来,而自信则是从自律来。 自律是对自我的控制,自信是对事情的控制。先学会克制自己,用严格的日程表控制生活,...

【玩儿法】真不是装X 为了不加班我一直用这些小众软件

[摘要]大部分用户在以实现某种功能去安装软件的时候都是非常盲目的。 文/周硕 很多身边的朋友常常问我的一个问题就是,“为什么我买来没多久的新电脑用用就慢了?有时候弹出奇怪的广告、弹窗,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程真不是好玩的
举报原因:
原因补充:

(最多只允许输入30个字)