我的Qt4代码使用一些QThread实例,这些实例在包含一些QString字段的通用数据结构上运行。它可以归结为以下内容:
我的数据结构:
class My : public QObject{
Q_OBJECT
public:
QString foo;
};
线程实现:
class Thr : public QThread{
public:
My* my;
protected:
void run(){
while (true){
QString copy = my->foo;
QString bar = copy.toUpper();
my->foo = bar.toLower();
}
}
};
这是为我的问题研究而编写的测试应用程序。当然,它并没有做任何实际有用的事情:)
如果我初始化的一个实例My
并使用该实例启动一个线程,那么一切都很好。但是,当我使用相同的My
实例启动第二个实例时,它会崩溃,并显示不同的消息,就像某些堆/堆栈/任何损坏的消息。
那是正常的吗?我知道一般的多线程问题以及Qt的QMutex都可以避免该问题。但是据我对Qt文档的正确理解,我可以这种方式使用它。我不能同时在同一个QString实例上进行操作(可能由于某种花哨的隐式共享机制而这样做-但文档指出这对用户是完全透明的?!)。
如前所述,我的问题不是关于如何重写代码,而是“从Qt 4开始”的内容,隐式共享类可以像在任何其他值类中一样安全地跨线程复制。它们是完全可重入的。隐式共享的确是隐含的。” (http://qt-project.org/doc/qt-4.8/threads-modules.html)我被误解了。
如注释中所述,您可能正在尝试从不同的线程写入相同的数据。我之所以写“大概”,是因为您尚未共享QThread
子类的用法。
正如评论中指出的那样,C ++标准甚至不保证分配对Object
带有QString
内部子类的类都是线程安全的。
您可以std::atomic
按提示使用,尽管仅从C ++ 11开始才可用。更加交叉的解决方案将是QMutex
用于您的方案,或者最好使用RAII解决方案,QMutexLocker
该解决方案将自动为您解决解锁问题。因此,您将像下面的代码一样。
class Thr : public QThread{
public:
My* my;
QMutex mutex; // <--- first addition
protected:
void run(){
while (true){
QString copy = my->foo;
QString bar = copy.toUpper();
QMutexLocker locker(&mutex); // <--- second addition
my->foo = bar.toLower();
}
}
};
当然,推荐的解决方案取决于其他因素,例如,您还可以根据手头的确切用例重新设计程序,使其不使用指针等。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句