我的Qt4代碼使用了一些QThread實例,它們在包含一些QString字段的公共數據結構上運行。它可以歸結爲以下幾點:Qt4 C++: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)我誤解了。
同時訪問同一對象,至少有一個如果是修改,則創建一個* data race *。具有數據競賽的程序具有未定義的行爲。在我看來,你的幾個線程正在同時修改(通過賦值)'my-> foo'('my-> foo = bar.toLower();')。 – Casey
好的,那麼在賦值中,'foo'實例可能處於不一致的'inbetween'狀態?我的確希望,至少使用這些非常基本的Qt類型的賦值本身是一個線程安全的操作,所以我可以同時訪問它,並且我可以獲得舊值或新值,但不會崩潰:)所以,我已經使用指針或互斥鎖,這並不能使代碼更具可讀性...... – ginger
C++不保證指針賦值是原子的;)任何你不包裹在「std :: atomic」中的東西都需要被保護以防數據競爭。 –
Casey