2012-12-13 16 views
4

我在ReadWrite模式下使用QBuffer。一名工人QThread將數據壓入緩衝區,另一名工人QThread從中讀取數據。Qt的QBuffer線程安全嗎?

是否QBuffer確保線程安全或我需要從QBuffer派生並添加互斥量?

+0

你只有一個pos(),所以你需要seek()和read()或write()在一個臨界區。另外,如果緩衝區爲空/滿,read()/ write()應該可能會被阻塞?這與QBuffer/QIODevice語義完全不同,並且值得它自己的類。 –

+0

QBuffer不是管道。它根本不適合你的使用,線程與否!你使用它的方式最終會耗盡內存,因爲緩衝區只能增長,永遠不會縮小。如果你想要一個呈現兩個QIODevices的類,比如管道的末端,你需要創建自己的。你也可以重用'QRingBuffer'('#include '),但訪問它必須受到互斥鎖保護。 –

+0

你真的*尋找什麼被稱爲[無鎖隊列](http://stackoverflow.com/questions/871234/circular-lock-free-buffer) - 看看最高的答案,它有優秀的引用。 –

回答

8

引述馬克·薩默的書C++ GUI Programming with Qt 4:

Qt的線程安全類包括QMutex,QMutexLocker,QReadWriteLock, QReadLocker,QWriteLocker,QSemaphore,QThreadStorage和 QWaitCondition。另外,部分QThread API和其他幾個函數都是線程安全的,特別是QObject :: connect(), QObject :: disconnect(),QCoreApplication :: postEvent()和 QCoreApplication :: removePostedEvents()。

Qt預計你將在其大部分類中使用鎖定機制。文檔會說「所有函數都是線程安全的」,如果它們是這樣的,並且各個函數也會指定「是線程安全的」。

Notes on Qt Classes

許多Qt類是可重入的,但它們不是 線程安全的,因爲使他們線程安全將會產生多次鎖定和解鎖QMutex的 額外的開銷。例如,對於 示例,QString是可重入的,但不是線程安全的。您可以安全地 同時從多個線程 訪問QString的不同實例,但您不能從多個線程同時安全地訪問同一個QString實例(除非您使用QMutex保護自己訪問 )。

某些Qt類和函數是線程安全的 。這些主要是線程相關類(例如QMutex) 和基本函數(例如QCoreApplication :: postEvent())。

因爲QBufferQIODevice直接子類我特別希望它不會是線程安全的,但也有是線程安全的讀訪問容器類,但需要鎖定的寫訪問:

Container Classes

容器類隱式共享,它們是可重入的,並且 它們是爲速度,低存儲器消耗和最小 內聯代碼擴充進行了優化,從而導致SMA ller可執行文件。此外, 它們在所有用於訪問它們的線程都用作只讀 容器的情況下是線程安全的。

+0

對,'QBuffer'不是線程安全的 –

1

擴展了QIODevice和文檔也指出,在QIODevice中所有的方法都是折返,但沒有指定最重要的是任何線程安全。鑑於QBuffer沒有提到更多,我期望QBuffer不是線程安全的。

http://qt-project.org/doc/qt-4.8/qiodevice.html

2

QBuffer是不是寫它使緩衝區增長,但是從中讀取在一開始並沒有刪除數據的線程之間溝通的最佳方式。

您可以改爲使用帶有參數QByteArray的信號/插槽,使用QLocalSocket或自己編寫一個從QIODevice派生的線程安全環形緩衝區類。

+0

非常好的一點。是的,我最終從'QIODevice'派生了我的自定義內存管理和線程安全鎖。另外,對於那些可能對這條路線感興趣並喜歡我的人,如果您需要優先考慮寫入操作或其他方式,請考慮在執行線程安全時使用'QReadWriteLock'而不是'QMutex'。 –

0

Qt中線程間最簡單的通信方式是將事件發佈到其他線程的事件隊列中。這假定其他線程旋轉事件循環。它只需要定期旋轉它,你通常會檢查新的數據等。

+0

您好,先生,您好!這些簡單的建議,尋求複雜的??肯定downvote! – mlvljr