首页 > 代码库 > c++多线程编程遇到的问题小结
c++多线程编程遇到的问题小结
众所周知,多线程编程很容易遇上诸如丢失更新、脏读、死锁等烦人的线程冲突问题。多线程的问题一旦发生便很难定位和解决,所以要在编程的初始阶段就要注意避免多线程程序常见的错误。下面总结一些个人在c++多线程编程中遇上的问题。
1、类中的数据成员要尽可能设置读写专用函数,并且在函数中用互斥锁进行并发保护。
解决线程冲突的最基本方法,不用多解释。
2、类中的成员函数要尽量避免在没有保护的情况下对某个成员变量的多次读取或者修改。
如果一个成员函数对某个成员变量多次读写,那么如果在这个函数对成员变量读写的期间其他并发线程也对成员变量进行了修改,这个成员函数的操作就很有可能被打乱并引发未知错误。
例:
class class1 {
char *text;
int func() {
if (text == 0) {
return -1;
}
cout<<*text<<endl;
return 0;
}
}
在上边的程序中,func成员函数首先检查text指针是否有效,如果有效,则打印其指向的内容。这种写法在串行下没有运行,但是如果是并行,就很有可能出现func函数刚刚判断完text指针不为空的一瞬间text指针被其他线程修改为NULL,之后func函数就会因为读写空指针而崩溃。
对于这个问题,即使你对text设置了带保护的读写函数,问题也依然存在。正确的解决办法是在读写成员变量前加锁,直到读写结束再释放锁。
3、如果一个加锁的函数调用另一个加锁的函数时,要注意检查连个函数是否使用了同一把锁。
这个问题很容易理解,如果两个函数用的是同一把锁,则就会造成死锁。其实避免这个问题的最好办法是避免在加锁的函数中进行复杂的函数调用。
4、对于加锁的不可重入的函数,要使用pthread_mutex_trylock
对一个函数加锁,只能保证一个函数不会被多个线程同时执行,但是无法避免多个线程先后执行同一个函数。
试想这么一种情况:有一个连接函数,当某个线程发现连接失败时就会调用这个连接函数,而这个连接函数又需要很长时间才能创建好连接。那么如果某一时刻若干个线程同时发现了连接失败,他们就会竞争调用连接函数。虽然连接函数加了锁可以避免被多个线程同时调用,但是当一个线程调用连接函数结束后,其他线程就会获得锁然后再次调用连接函数,如果此时有100个线程在试图调用连接函数,那么连接就会被重复进行100次,白白浪费了资源。
解决上述问题的方法很简单,就是实现当一个线程正在执行连接函数的时候,其他线程不再执行连接函数,而不是等待这个线程执行完后再执行一遍。实现这个可以用trylock函数。大部分人对于互斥锁仅仅停留在lock和unlock上,其实trylock也是一个非常好用的函数,这个函数就是lock的非阻塞版,不用多解释了吧。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。