|
無論如何,要編寫一個多執行緒安全(thread-safe)的程式總是困難的,為了使用的共用資源,您必須小心
的對共用資源進行同步,同步帶來一定的效
能延遲,而另一方面,在處理同步的時候,又要注意物件的鎖定與釋放,避免產生死結,種種因素都使得編寫多執行緒程式變得困難。 Thread-Specific Storage模式嘗試從另一個角度來解釋多執行緒共用資源的問題,其思考點很簡單,即然共用資源這麼困難,那麼就乾脆不要共用,何不為每個執行緒創造一 個資源的複本,將每一個執行緒存取資料的行為加以隔離,其實現的方法,就是給予每一個執行緒一個特定空間來保管該執行緒所獨享的資源,也因此而稱之為 Thread- Specific Storage模式。 實作Thread-Specific Storage模式,最基本的方式,就是使用一個關聯容器物件,例如 關 聯容器(QMap、QHash...),在執行緒獲得個別資源時,使用QThread::currentThread()取得執行緒ID,將ID為鍵(Key)、資源為值(Value)存入關聯容器之中,要取得執行緒個別資源時,則以執行緒ID為鍵來取得相對應的資源。 下面這個簡單的MessageThreadLocal簡單實作了Thread-Specific Storage的概念: class MessageThreadLocal {
public: QString get(); void set(const QString &message); private: QMap<QThread*, QString> map; }; QString MessageThreadLocal::get() { QThread *thread = QThread::currentThread(); QString message = map.value(thread, "N.A."); if(message == "N.A." && !map.contains(thread)) { map.insert(thread, "N.A."); } return message; } void MessageThreadLocal::set(const QString &message) { map.insert(QThread::currentThread(), message); } 在Qt 中,您不用親自實作這樣的ThreadLocal類別,它提供有QThreadStorage類別,可以讓您直接用來實現Thread-Specific Storage模式,例如API文件中QThreadStorage的說明中,提供一個簡單的範例片段,示範如何為每個執行緒儲存一個快取物件: QThreadStorage<QCache<QString, SomeClass> *> caches;
void cacheObject(const QString &key, SomeClass *object) { if (!caches.hasLocalData()) caches.setLocalData(new QCache<QString, SomeClass>); caches.localData()->insert(key, object); } void removeFromCache(const QString &key) { if (!caches.hasLocalData()) return; caches.localData()->remove(key); } 使用QThreadStorage時要注意的是,由於某些編譯器的限制,QThreadStorage只能儲存指標。 |
|