线程

在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。

判断是否在同一个线程中的根本方法也比较简单,在Windows上直接用 GetCurrentThreadId() 比较;

GetCurrentThreadId() 会直接输出线程id。

注意:

1.线程id是动态分配的,因此如果某一个线程结束以后,这个id号还可能会分配给另一个线程,所以会有重复。

2.之所以会出现相同ID的情况,可能是以下原因:先前的线程已经被销毁了;采用的是异步机制;消息机制;线程运行得太短时间了,还没有等其它线程启动就已经运行完了。

3.直接输出了GetCurrentThreadID的返回值可能会出现重复的现象,

这个返回值不能直接输出的,该函数采用的是寄存器返回,很快会被其他操作覆盖!

正确的做法是:

将GetCurrentThreadID的返回值赋值给一个临时变量;而后输出该临时变量

以前自己将GetCurrentThreadID的值作为map的key,也出了问题,改用临时变量就解决了。

4.打印出id的那句是:

TRACE("Current Thread ID = 0x%X\n", AfxGetThread()->m_nThreadID);

直接输出也可以。

一、关于设置断点和单步执行

很多同学非常依赖于调试器的断点功能和单步功能。这在单线程情况下倒还好(不过有些单线程但涉及GUI的程序,也会有点麻烦)。至于多线程程序的调试,这两种手段简直就是噩梦的开始。多线程造成的主要问题大都和竞态条件(Race Condition,详细解释看“这里 ”)有关。

而设置断点或单步跟踪可能会严重干扰 多线程之间的竞争状态。导致你看到的是一个假象。比如本来有两个线程并发执行,存在某些不和谐的Bug(由竞态引起)。一旦你在某一个线程设置了断点,该线程在断点处停住了,只剩下另一个线程在跑。这时候,并发的场景已经完全被破坏了,你通过调试器看到的可能 是一个和谐的场景。

稍微跑一下题。这很类似量子力学的“测不准原理”,观测者的观测行为干扰了被测量的客体,导致观测者看到的是一个干扰后的现象。

二、关于Log输出

既然断点和单步不好用。那咋办捏?一个替代方案是输出log日志。它可以有效减轻断点和单步所导致的(针对竞态条件的)副作用。

1、传统Log机制的问题

传统的log输出主要是打印到屏幕或者输出到文件。对于C++而言,标准库内置的类和函数(比如cout、printf、fputs)可能会有线程安全的问题(和编译器的具体实现有关)。尤其是标准流类库(iostream)的八个全局对象,更是要小心慎用。轻则输出的log文本混杂,重则导致程序崩溃。

鉴于上述原因,应该尽量使用第三方线程库内置的log机制来搞定log输出功能。比如ACE内置的ACE_Log_Msg等。

2、Log函数要短小精悍

很多情况下,我们会包装一个公用的函数来实现log输出功能。然后在该函数内部调用线程库的log类/函数。为了不影响线程的竞态条件,这个log函数要尽可能简单轻便:不要涉及太多杂七杂八的琐事、千万别进行耗时的操作、尽量不操作一些全局的变量。

3、Log的副作用

不过捏,即使log函数再短小精悍,也还是有可能影响竞态条件(毕竟log也有开销,也要消耗CPU时间)。

万一竞态条件受到log的影响,那就比较棘手了。我以前就碰到过这种情况:加了log,程序没有问题;去掉log,程序随机崩溃。这种情况一般有两种可能:要么是log功能本身有问题,要么是程序的竞态条件非常敏感(连log的开销都会有影响)。

这时候你能依靠的就只有肉眼和人脑了。先把相关的代码和文档仔细看上几遍(最好再找其他有经验的人一起Code Review),然后大家一起开动脑筋使劲琢磨。

三、关于Debug版本和Release版本

C++程序经常有Debug版本和Release版本的区别。有些时候,这也会导致一些多线程的问题。

由于Debug版本包含了一些调试信息、启用了某些调试机制(比如assert宏)。所以就可能 影响到多线程的竞争状态。在倒霉的时候,会碰上Debug版本工作正常,Release版本程序随机崩溃。要避免这种情况,可以考虑下面两个办法:

1、放弃使用Debug版本

你可以干脆放弃使用Debug版本。在这种情况下,你需要考虑把诸如assert之类调试相关的宏替换成自己的一套宏,使得在非Debug版本下也可以生效。

2、两种版本同步测试

使用此方法,程序员平时自测可以使用Debug版本,但是测试人员日常测试的必须是Release版本。具体的操作步骤可以利用每日构建来辅助进行(每日构建的介绍参见“这里 ”)。一定要避免:在平时仅仅搞Debug版本的测试,等到发布前夕再制作Release版本。这种做法是非常危险的!

判断是否在同一个线程-GetCurrentThreadId()用法的更多相关文章

  1. 解析Qt元对象系统(五) Q_INVOKABLE与invokeMethod(automatic connection从Qt4.8开始的解释已经与之前不同,发送对象驻足于哪一个线程并不重要,起到决定作用的是接收者对象所驻足的线程以及发射信号(该信号与接受者连接)的线程是不是在同一个线程)good

    概述查看Qt源码可知,Q_INVOKABLE是个空宏,目的在于让moc识别. 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起. Q_INVOKABLE与QMe ...

  2. java中判断list是否为空的用法

    1.如果想判断list是否为空,可以这么判断: if(null == list || list.size() ==0 ){ //为空的情况 }else{ //不为空的情况 } 2.list.isEmp ...

  3. 四种Java线程池用法解析

    本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 执行一个异步任务你还只是如下 ...

  4. Java集合的线程安全用法

    线程安全的集合包含2个问题 1.多线程并发修改一 个 集合 怎么办? 2.如果迭代的过程中 集合 被修改了怎么办? a.一个线程在迭代,另一个线程在修改 b.在同一个线程内用同一个迭代器对象进行迭代. ...

  5. 如何判断C#的Finalizer线程有没有被阻塞

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何判断C#的Finalizer线程有没有被阻塞.

  6. C#线程池用法

    C#线程池用法 在C#编程语言中,使用线程池可以并行地处理工作,当强制线程和更新进度条时,会使用内建架构的ThreadPool类,为批处理使用多核结构,这里我们来看在C#编程语言中一些关于来自Syst ...

  7. c/c++ 多线程 多个线程等待同一个线程的一次性事件

    多线程 多个线程等待一个线程的一次性事件 背景:从多个线程访问同一个std::future,也就是多个线程都在等待同一个线程的结果,这时怎么处理. 办法:由于std::future只能被调用一次get ...

  8. 如何判断是否为同一个App,Ionic3如何修改包名

    如何判断是否同一个App 使用Ionic3创建了两个项目demo1.demo2,然后使用同一个JDK,生成了两个不同的keystore证书. 结果在手机端安装的时候,先安装demo1,没有任何替换的提 ...

  9. 同一个线程多次调用start()会出现的问题

    结果: 线程首先会运行一次,然后抛出java.lang.IllegalThreadStateException异常. 根据控制台的异常信息,定位到Thread.java的第708行,也就start() ...

随机推荐

  1. ETH跌破400美元大关 一场收割全球的计划完成闭环

    ETH跌破400美元大关 一场收割全球的计划完成闭环 三大交易所,ETH的价格均跌下400美元,看空者占比近80%. 在普通人眼里,这可能只是熊市的一个自然表现. 但事实完全不是这样.这本质上一场历时 ...

  2. make: *** /lib/modules/3.10.0-327.el7.x86_64/build: 没有那个文件或目录。 停止。

    1.问题: [root@localhost]# make make -C /lib/modules/-.el7.x86_64/build M=/home/csri/poc/adore modules ...

  3. [转载]Oracle左连接、右连接、全外连接以及(+)号用法

    Oracle  外连接(OUTER JOIN) 左外连接(左边的表不加限制) 右外连接(右边的表不加限制) 全外连接(左右两表都不加限制) 对应SQL:LEFT/RIGHT/FULL OUTER JO ...

  4. [转载] c#中decimal ,double,float的区别

    一直很奇怪C#的预定义数据类型中为什么加了一个decimal,有float和double不就够了吗?今天来挖一挖. 浮点型 Name CTS Type De script ion Significan ...

  5. How to use Nissan consult 3 plus to check, make key and program?

    How to use Nissan consult 3 plus to test Nissan? Firstly: get one particular Nissan consult 3 plus. ...

  6. 自学Java第四周的总结

    在这一周里我主要把以前学的知识复习了一遍,加深了自己对那些知识点的熟悉程度.另外我还学习了有关于Java中的异常处理.继承.抽象类等相关知识.了解了其基本意义,即继承是java面向对象编程技术的一块基 ...

  7. django 上传文件及反馈信息

    from django.shortcuts import render,HttpResponse from django.views import View from Fiskars.models i ...

  8. Web安全学习笔记之更新kali国内源

    vi /etc/apt/sources.list #中科大 deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib ...

  9. P2044 [NOI2012]随机数生成器

    洛咕原题 正常的矩乘题. 但是,计算过程中会爆long long. 所以,我们要用快速(龟速)乘来解决. 快速乘,也就是把快速幂稍作修改.乘法被分成若干个加法,以时间为代价解决精度问题. #inclu ...

  10. DDoS防御方案

    转自:http://netsecurity.51cto.com/art/201211/368930.htm 深入浅出DDoS攻击防御应对篇:DDoS防御方案 谈到DDoS防御,首先就是要知道到底遭受了 ...