2016-12-26 92 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()”中最小的可能关键部分。