2016-12-26 37 views
0

我有一個函數,多個線程可以同時調用它。這個函數有一個輸入參數。例如,請考慮以下功能:使用多線程中的輸入參數調用函數

bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    ... 
} 

我有兩個使用此功能的選項。調用像下面這個函數的時候

... 
run("Reza"); // can be different for different threads 
... 
bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    QMutexLocker locker(&runMutex); 
    ... 
} 

二是使用互斥:

... 
runMutex.lock(); 
run("Reza"); // can be different for different threads 
runMutex.unlock(); 
... 
bool MyClass::run(QString moduleName) 
{ 
    qDebug() << QThread::currentThreadId(); 
    ... 
} 

哪一個是正確的,更好的首先,我可以用一個互斥run函數裏面像下面?輸入參數(moduleName)是否在第一個選項中更改? (我的意思是當調用線程通過此功能不同的參數)

在此先感謝您的幫助。 Reza

+1

你想用你的互斥鎖保護哪個資源? (並且'qDebug()'在你的第一個片段中沒有被保護)。 – Jarod42

+0

定義「更好」... –

+0

@ Jarod42我有我的「運行」功能,我想用互斥保護一些共同的資源。我知道qDebug()沒有被保護。 – Reza

回答

1

在很多情況下,都是!內部獲取互斥鎖的功能使這個功能更容易使用,而且通常更安全。但是,當明確使用互斥鎖時,除了通過run()方法完成的操作外,還需要執行其他操作,同時也持有該鎖。在這種情況下,你會有另一個獲取鎖的函數,它不能調用內部鎖定函數(當然,除非互斥鎖是一個遞歸互斥鎖,我認爲它並不是一個好主意)。出路在於具有該功能的版本,例如run_locked()或具有假定獲取鎖的不同參數的版本。當我使用顯式鎖定(我通常儘量避免這樣做,因爲我不能推斷使用鎖的代碼)我發現有這樣的功能對應的對(我通常使用std設施)是有幫助的:

bool MyClass::run(QString moduleName) { 
    QMutexLocker kerberos(&runMutex); 
    return this->run(kerberos, moduleName); 
} 
bool MyClass::run(QMutexLocker& kerberos, QString moduleName) { 
    // do whatever work is needed here 
} 

穿過鎖定後衛對象確保有一個收購後衛左右,即用戶不能只調用沒有任何收購鎖定擋板被收購預期鎖的功能。通過爲錯誤鎖定獲得鎖守可能存在誤用。

+0

@Kuhl感謝您的及時和全面的回覆。調用函數的輸入參數怎麼樣?是否有任何線程在其自己的堆棧中有其副本,或者它對所有線程都很常見? – Reza

+1

@Reza:你的意思是'moduleName'?它通過的方式是價值,即每個線程都有自己的價值。但我對'QString'一無所知,如果它使用共享表示(例如,寫入字符串上的副本),則可能仍然存在一些問題。如果你使用'std :: string'(以及至少在C++ 11之後的C++實現),那麼保證字符串表示不被共享,並且在訪問通過value傳遞的參數時不需要鎖定。 –

+0

這個答案沒有提到互斥體的目的,並且明確定義可能受其保護的資源,這個答案就沒有多大意義。也許這是因爲這個問題也非常不清楚。 –

1

兩種方法都是正確的,但第一種方法是更好的方法。它還提供了代碼可讀性。

在第一個選項中,輸入參數(局部變量)參數總是安全的。因爲每個線程都有自己的堆棧。

1

DietmarKühl爲選擇上述方法提供了很好的答案。但是,我想補充一點,最小化臨界區總是一個好的做法。因此,如果您不需要鎖定整個「run()」函數,則應該既不使用上述方法,也不使用「run()」中最小的可能關鍵部分。