问题
在和队友一起调试项目时,队友在项目的某一个地方用到了多线程,主要是为了在保证主线程正常运行的情况下检测一个鼠标的点击事件,通过对于一个flag变量的判断从而进行暂停的功能。但是我在pull项目后本地调试时,却发现这个暂停点了之后可以暂停,可是再点继续的时候却无法继续,但是去询问队友他本地却运行正常。
解决
后来发现队友那边是使用的是debug模式,而我这里运行时使用的是release模式,可以看出又是一些ub行为导致的问题。
最后查阅了相关资料等等,发现了问题产生的原因是release模式下对于变量的存储进行了优化,因为程序本来是在点击暂停之后一直检测flag变量isPause是否为否,而由于该变量被频繁访问,所以可能会被优化到CPU中存储(register),这就导致了子线程对其的修改失效了,两者修改检测的不是同一个变量,所以导致了暂停后不能继续的bug。
解决方法就是通过volatile关键词进行修饰,避免被优化。
在多线程中若想通过一个公共的flag变量进行线程间的通信,记得要进行volatile修饰,避免编译器的优化。
后续更新
后面了解到volatile其实不是很适用在这种场景里面(虽说在整个项目里面确实能够达到目的)。实际上更科学的做法是应该使用mutex或者atomic,尤其是在学习了操作系统之后,更是意识到对于这种共享资源,应该进行加锁,pv操作进行处理。同时,c++11也为我们提供了原子(atomic)数据类型,能够正确实现对于共享资源变量的访问,并且相比于加锁操作能够提高相当高的效率。而volatile貌似现在更多用于硬件、单片机层面(?